Coverage Report

Created: 2026-04-12 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/pkcs15init/pkcs15-cflex.c
Line
Count
Source
1
/*
2
 * Cryptoflex specific operation for PKCS #15 initialization
3
 *
4
 * Copyright (C) 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include "config.h"
22
23
#include <stdlib.h>
24
#include <string.h>
25
#include <sys/types.h>
26
27
#include "libopensc/opensc.h"
28
#include "libopensc/cardctl.h"
29
#include "libopensc/log.h"
30
#include "pkcs15-init.h"
31
#include "profile.h"
32
33
static void invert_buf(u8 *dest, const u8 *src, size_t c);
34
static int  cflex_create_dummy_chvs(sc_profile_t *, sc_pkcs15_card_t *,
35
      sc_file_t *, int,
36
      sc_file_t **);
37
static void cflex_delete_dummy_chvs(sc_profile_t *, sc_pkcs15_card_t *,
38
      int, sc_file_t **);
39
static int  cflex_create_pin_file(sc_profile_t *, sc_pkcs15_card_t *,
40
      sc_path_t *, int,
41
      const u8 *, size_t, int,
42
      const u8 *, size_t, int,
43
      sc_file_t **, int);
44
static int  cflex_create_empty_pin_file(sc_profile_t *, sc_pkcs15_card_t *,
45
      sc_path_t *, int, sc_file_t **);
46
static int  cflex_get_keyfiles(sc_profile_t *, sc_card_t *,
47
      const sc_path_t *, sc_file_t **, sc_file_t **);
48
49
unsigned char dummy_pin_value[6] = {0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
50
51
static int
52
cflex_delete_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df)
53
0
{
54
0
        sc_path_t  path;
55
0
        sc_file_t  *parent;
56
0
        int             r = 0;
57
        /* Select the parent DF */
58
0
        path = df->path;
59
0
    if (path.len < 2) {
60
0
      return SC_ERROR_INVALID_ARGUMENTS;
61
0
    }
62
0
        path.len -= 2;
63
0
        r = sc_select_file(p15card->card, &path, &parent);
64
0
        if (r < 0)
65
0
                return r;
66
67
0
        r = sc_pkcs15init_authenticate(profile, p15card, parent, SC_AC_OP_DELETE);
68
0
        sc_file_free(parent);
69
0
        if (r < 0)
70
0
                return r;
71
72
  /* cryptoflex has no ERASE AC */
73
0
        memset(&path, 0, sizeof(path));
74
0
        path.type = SC_PATH_TYPE_FILE_ID;
75
0
        path.value[0] = df->id >> 8;
76
0
        path.value[1] = df->id & 0xFF;
77
0
        path.len = 2;
78
79
0
  r = sc_delete_file(p15card->card, &path);
80
0
  return r;
81
0
}
82
83
/*
84
 * Erase the card via rm
85
 */
86
static int cflex_erase_card(struct sc_profile *profile, sc_pkcs15_card_t *p15card)
87
0
{
88
0
  struct sc_context *ctx = p15card->card->ctx;
89
0
  sc_file_t  *df = profile->df_info->file, *dir, *userpinfile = NULL;
90
0
  int             r;
91
92
0
  LOG_FUNC_CALLED(ctx);
93
  /* Delete EF(DIR). This may not be very nice
94
         * against other applications that use this file, but
95
         * extremely useful for testing :)
96
         * Note we need to delete if before the DF because we create
97
         * it *after* the DF.
98
         * */
99
0
        if (sc_profile_get_file(profile, "DIR", &dir) >= 0) {
100
0
                r = cflex_delete_file(profile, p15card, dir);
101
0
                sc_file_free(dir);
102
0
                if (r < 0 && r != SC_ERROR_FILE_NOT_FOUND)
103
0
                        goto out;
104
0
        }
105
106
0
  r=cflex_delete_file(profile, p15card, df);
107
108
  /* If the user pin file isn't in a sub-DF of the pkcs15 DF, delete it */
109
0
  if (sc_profile_get_file(profile, "pinfile-1", &userpinfile) >= 0 &&
110
0
      userpinfile->path.len <= profile->df_info->file->path.len + 2 &&
111
0
      memcmp(userpinfile->path.value, profile->df_info->file->path.value,
112
0
             userpinfile->path.len) != 0) {
113
0
            r = cflex_delete_file(profile, p15card, userpinfile);
114
0
    sc_file_free(userpinfile);
115
0
    userpinfile=NULL;
116
0
  }
117
118
119
0
out:  /* Forget all cached keys, the pin files on card are all gone. */
120
0
  sc_file_free(userpinfile);
121
122
0
        sc_free_apps(p15card->card);
123
0
        if (r == SC_ERROR_FILE_NOT_FOUND)
124
0
                r=0;
125
126
0
  SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
127
0
}
128
129
/*
130
 * Card initialization.
131
 * For the cryptoflex, read the card's serial number from 3F00 0002
132
 */
133
static int
134
cryptoflex_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card)
135
0
{
136
0
  sc_path_t path;
137
0
  sc_file_t *file;
138
0
  u8    buf[32];
139
0
  char    serial[128];
140
0
  size_t    len;
141
0
  int   r;
142
143
0
  sc_format_path("3F000002", &path);
144
0
  if ((r = sc_select_file(p15card->card, &path, &file)) < 0) {
145
0
    if (r == SC_ERROR_FILE_NOT_FOUND)
146
0
      return 0;
147
0
    return r;
148
0
  }
149
150
0
  if ((len = file->size) > sizeof(buf))
151
0
    len = sizeof(buf);
152
0
  sc_file_free(file);
153
0
  if ((r = sc_read_binary(p15card->card, 0, buf, len, 0)) < 0)
154
0
    return r;
155
0
  len = r;
156
0
  if (len == 0)
157
0
    return 0;
158
159
0
  if ((r = sc_bin_to_hex(buf, len, serial, sizeof(serial), '\0')) < 0)
160
0
    return r;
161
0
  sc_pkcs15init_set_serial(profile, serial);
162
0
  return 0;
163
0
}
164
165
/*
166
 * Create a DF
167
 */
168
static int
169
cflex_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df)
170
0
{
171
  /* Create the application DF */
172
0
  return sc_pkcs15init_create_file(profile, p15card, df);
173
0
}
174
175
/*
176
 * Create a PIN domain (i.e. a sub-directory holding a user PIN)
177
 */
178
static int
179
cflex_create_domain(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
180
    const sc_pkcs15_id_t *id, sc_file_t **ret)
181
0
{
182
0
  return sc_pkcs15_create_pin_domain(profile, p15card, id, ret);
183
0
}
184
185
/*
186
 * Select the PIN reference
187
 */
188
static int
189
cflex_select_pin_reference(sc_profile_t *profike, sc_pkcs15_card_t *p15card,
190
    sc_pkcs15_auth_info_t *auth_info)
191
0
{
192
0
  int preferred;
193
194
0
  if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
195
0
    return SC_ERROR_OBJECT_NOT_VALID;
196
197
0
  if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
198
0
    preferred = 2;
199
0
  } else {
200
0
    preferred = 1;
201
0
  }
202
0
  if (auth_info->attrs.pin.reference <= preferred) {
203
0
    auth_info->attrs.pin.reference = preferred;
204
0
    return 0;
205
0
  }
206
207
0
  if (auth_info->attrs.pin.reference > 2)
208
0
    return SC_ERROR_INVALID_ARGUMENTS;
209
210
  /* Caller, please select a different PIN reference */
211
0
  return SC_ERROR_INVALID_PIN_REFERENCE;
212
0
}
213
214
215
/*
216
 * Create a new PIN inside a DF
217
 */
218
static int
219
cflex_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df,
220
    sc_pkcs15_object_t *pin_obj,
221
    const u8 *pin, size_t pin_len,
222
    const u8 *puk, size_t puk_len)
223
0
{
224
0
  struct sc_context *ctx = p15card->card->ctx;
225
0
  sc_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data;
226
0
  struct sc_pkcs15_pin_attributes *pin_attrs = &auth_info->attrs.pin;
227
0
  sc_file_t *dummies[2];
228
0
  int   ndummies, pin_type, puk_type, r;
229
0
  sc_file_t       *file = NULL;
230
231
0
  LOG_FUNC_CALLED(ctx);
232
233
0
  if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN)
234
0
    return SC_ERROR_OBJECT_NOT_VALID;
235
236
  /* If the profile doesn't specify a reference for this PIN, guess */
237
0
  if (pin_attrs->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
238
0
    pin_type = SC_PKCS15INIT_SO_PIN;
239
0
    puk_type = SC_PKCS15INIT_SO_PUK;
240
0
    if (pin_attrs->reference != 2)
241
0
      return SC_ERROR_INVALID_ARGUMENTS;
242
0
  } else {
243
0
    pin_type = SC_PKCS15INIT_USER_PIN;
244
0
    puk_type = SC_PKCS15INIT_USER_PUK;
245
0
    if (pin_attrs->reference != 1)
246
0
      return SC_ERROR_INVALID_ARGUMENTS;
247
0
  }
248
249
  /* Get file definition from the profile */
250
0
  if (sc_profile_get_file(profile, (pin_attrs->reference == 1)? "CHV1" : "CHV2", &file) < 0
251
0
      && sc_profile_get_file(profile, "CHV", &file) < 0)
252
0
    LOG_TEST_RET(ctx, SC_ERROR_FILE_NOT_FOUND, "profile does not define pin file ACLs");
253
254
0
  ndummies = cflex_create_dummy_chvs(profile, p15card, file, SC_AC_OP_CREATE, dummies);
255
0
  sc_file_free(file);
256
0
  LOG_TEST_RET(ctx, ndummies, "Unable to create dummy CHV file");
257
258
0
  r = cflex_create_pin_file(profile, p15card, &df->path, pin_attrs->reference,
259
0
      pin, pin_len, sc_profile_get_pin_retries(profile, pin_type),
260
0
      puk, puk_len, sc_profile_get_pin_retries(profile, puk_type),
261
0
      NULL, 0);
262
263
0
  cflex_delete_dummy_chvs(profile, p15card, ndummies, dummies);
264
0
  SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
265
0
}
266
267
/*
268
 * Create a new key file
269
 */
270
static int
271
cflex_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj)
272
0
{
273
0
  sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
274
0
  sc_file_t *prkf = NULL, *pukf = NULL;
275
0
  size_t    size;
276
0
  int   r;
277
278
0
  if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
279
0
    sc_log(p15card->card->ctx,  "Cryptoflex supports only RSA keys.");
280
0
    return SC_ERROR_NOT_SUPPORTED;
281
0
  }
282
283
  /* Get the public and private key file */
284
0
  r = cflex_get_keyfiles(profile, p15card->card,  &key_info->path, &prkf, &pukf);
285
0
  if (r < 0)
286
0
    return r;
287
288
  /* Adjust the file sizes, if necessary */
289
0
  switch (key_info->modulus_length) {
290
0
  case  512: size = 166; break;
291
0
  case  768: size = 246; break;
292
0
  case 1024: size = 326; break;
293
0
  case 2048: size = 646; break;
294
0
  default:
295
0
    sc_log(p15card->card->ctx,
296
0
       "Unsupported key size %"SC_FORMAT_LEN_SIZE_T"u\n",
297
0
       key_info->modulus_length);
298
0
    r = SC_ERROR_INVALID_ARGUMENTS;
299
0
    goto out;
300
0
  }
301
302
0
  if (prkf && prkf->size < size)
303
0
    prkf->size = size;
304
0
  if (pukf && pukf->size < size + 4)
305
0
    pukf->size = size + 4;
306
307
  /* Now create the files */
308
0
  if ((r = sc_pkcs15init_create_file(profile, p15card, prkf)) < 0
309
0
   || (r = sc_pkcs15init_create_file(profile, p15card, pukf)) < 0)
310
0
    goto out;
311
312
0
  key_info->key_reference = 0;
313
314
0
out:  sc_file_free(prkf);
315
0
  sc_file_free(pukf);
316
0
  return r;
317
0
}
318
319
320
/*
321
 * Generate key
322
 */
323
static int
324
cflex_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
325
      sc_pkcs15_object_t *obj,
326
      sc_pkcs15_pubkey_t *pubkey)
327
0
{
328
0
  struct sc_cardctl_cryptoflex_genkey_info args;
329
0
  sc_card_t *card = p15card->card;
330
0
  sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
331
0
  size_t  keybits;
332
0
  unsigned char raw_pubkey[256];
333
0
  sc_file_t *prkf = NULL, *pukf = NULL;
334
0
  int   r;
335
336
0
  if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
337
0
    sc_log(card->ctx,  "Cryptoflex supports only RSA keys.");
338
0
    return SC_ERROR_NOT_SUPPORTED;
339
0
  }
340
  /* Get the public and private key file */
341
0
  r = cflex_get_keyfiles(profile, card, &key_info->path, &prkf, &pukf);
342
0
  if (r < 0)
343
0
    return r;
344
0
  if (! prkf)
345
0
    return SC_ERROR_NOT_SUPPORTED;
346
347
  /* Make sure we authenticate first */
348
0
  r = sc_pkcs15init_authenticate(profile, p15card, prkf, SC_AC_OP_CRYPTO);
349
0
  if (r < 0)
350
0
    goto out;
351
352
0
  keybits = key_info->modulus_length;
353
354
  /* Perform key generation */
355
0
  memset(&args, 0, sizeof(args));
356
0
  args.exponent = 0x10001;
357
0
  args.key_bits = keybits;
358
0
  args.key_num  = key_info->key_reference;
359
0
  r = sc_card_ctl(card, SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY, &args);
360
0
  if (r < 0)
361
0
    goto out;
362
363
  /* extract public key */
364
0
  pubkey->algorithm = SC_ALGORITHM_RSA;
365
0
  pubkey->u.rsa.modulus.len   = keybits / 8;
366
0
  pubkey->u.rsa.modulus.data  = malloc(keybits / 8);
367
0
  pubkey->u.rsa.exponent.len  = 3;
368
0
  pubkey->u.rsa.exponent.data = malloc(3);
369
0
  memcpy(pubkey->u.rsa.exponent.data, "\x01\x00\x01", 3);
370
0
  if ((r = sc_select_file(card, &pukf->path, NULL)) < 0
371
0
   || (r = sc_read_binary(card, 3, raw_pubkey, keybits / 8, 0)) < 0)
372
0
    goto out;
373
374
0
  invert_buf(pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len);
375
376
0
out:  sc_file_free(pukf);
377
0
  sc_file_free(prkf);
378
0
  return r;
379
0
}
380
381
/*
382
 * Store a private key
383
 */
384
static int
385
cflex_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
386
    sc_pkcs15_object_t *obj,
387
    sc_pkcs15_prkey_t *key)
388
0
{
389
0
  sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
390
0
  sc_card_t *card = p15card->card;
391
0
  sc_file_t *prkf = NULL, *pukf = NULL;
392
0
  unsigned char keybuf[1024];
393
0
  size_t    size;
394
0
  int   r;
395
396
0
  if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
397
0
    sc_log(card->ctx,  "Cryptoflex supports only RSA keys.");
398
0
    return SC_ERROR_NOT_SUPPORTED;
399
0
  }
400
  /* Get the public and private key file */
401
0
  r = cflex_get_keyfiles(profile, card, &key_info->path, &prkf, &pukf);
402
0
  if (r < 0)
403
0
    return r;
404
405
  /* Write the private key */
406
0
  size = sizeof(keybuf);
407
0
  r = profile->ops->encode_private_key(profile, card,
408
0
        &key->u.rsa, keybuf, &size,
409
0
        key_info->key_reference);
410
0
  if (r < 0)
411
0
    goto out;
412
413
0
  r = sc_pkcs15init_update_file(profile, p15card, prkf, keybuf, (unsigned)size);
414
0
  if (r < 0)
415
0
    goto out;
416
417
  /* Write the public key */
418
0
  size = sizeof(keybuf);
419
0
  r = profile->ops->encode_public_key(profile, card,
420
0
        &key->u.rsa, keybuf, &size,
421
0
        key_info->key_reference);
422
0
  if (r < 0)
423
0
    goto out;
424
425
0
  r = sc_pkcs15init_update_file(profile, p15card, pukf, keybuf, (unsigned)size);
426
427
0
out:  sc_file_free(prkf);
428
0
  sc_file_free(pukf);
429
0
  return r;
430
0
}
431
432
/*
433
 * If an access condition references e.g. CHV1, but we don't have
434
 * a CHV1 file yet, create an unprotected dummy file in the MF.
435
 */
436
static int
437
cflex_create_dummy_chvs(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
438
      sc_file_t *file, int op,
439
      sc_file_t **dummies)
440
0
{
441
0
  struct sc_context *ctx = p15card->card->ctx;
442
0
  const sc_acl_entry_t *acl;
443
0
  int   r = 0, ndummies = 0;
444
445
0
  LOG_FUNC_CALLED(ctx);
446
  /* See if the DF is supposed to be PIN protected, and if
447
   * it is, whether that CHV file actually exists. If it doesn't,
448
   * create it.
449
   */
450
0
  acl = sc_file_get_acl_entry(file, op);
451
0
  for (; acl; acl = acl->next) {
452
0
    sc_path_t parent, ef;
453
454
0
    if (acl->method != SC_AC_CHV)
455
0
      continue;
456
457
0
    parent = file->path;
458
0
    parent.len -= 2;
459
460
0
    r = SC_ERROR_FILE_NOT_FOUND;
461
0
    while (parent.len >= 2 && r == SC_ERROR_FILE_NOT_FOUND) {
462
0
      ef = parent;
463
0
      ef.value[ef.len++] = acl->key_ref - 1;
464
0
      ef.value[ef.len++] = 0;
465
0
      parent.len -= 2;
466
467
0
      if (ef.len == parent.len
468
0
       && !memcmp(ef.value, parent.value, ef.len))
469
0
        continue;
470
471
0
      r = sc_select_file(p15card->card, &ef, NULL);
472
0
    }
473
474
    /* If a valid EF(CHVx) was found, we're fine */
475
0
    if (r == 0)
476
0
      continue;
477
0
    if (r != SC_ERROR_FILE_NOT_FOUND)
478
0
      break;
479
480
    /* Create a CHV file in the MF */
481
0
    parent = file->path;
482
0
    parent.len = 2;
483
0
    r = cflex_create_empty_pin_file(profile, p15card, &parent,
484
0
        acl->key_ref, &dummies[ndummies]);
485
0
    if (r < 0)
486
0
      break;
487
0
    ndummies++;
488
0
  }
489
490
0
  if (r < 0) {
491
0
    cflex_delete_dummy_chvs(profile, p15card, ndummies, dummies);
492
0
    return r;
493
0
  }
494
495
0
  SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, ndummies);
496
0
}
497
498
static void
499
cflex_delete_dummy_chvs(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
500
      int ndummies, sc_file_t **dummies)
501
0
{
502
0
  while (ndummies--) {
503
0
    cflex_delete_file(profile, p15card, dummies[ndummies]);
504
0
    sc_file_free(dummies[ndummies]);
505
0
  }
506
0
}
507
508
/*
509
 * Create a pin file
510
 */
511
static void put_pin(sc_profile_t *profile, unsigned char *buf,
512
    const u8 *pin, size_t len, int retry)
513
0
{
514
0
  if (len > 8)
515
0
    len = 8;
516
0
  memset(buf, profile->pin_pad_char, 8);
517
0
  memcpy(buf, pin, len);
518
0
  buf[8] = retry;
519
0
  buf[9] = retry;
520
0
}
521
522
static int
523
cflex_create_pin_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
524
      sc_path_t *df_path, int ref,
525
      const u8 *pin, size_t pin_len, int pin_tries,
526
      const u8 *puk, size_t puk_len, int puk_tries,
527
      sc_file_t **file_ret, int unprotected)
528
0
{
529
0
  struct sc_context *ctx = p15card->card->ctx;
530
0
  struct sc_pkcs15_object *pin_obj = NULL;
531
0
  unsigned char buffer[23];
532
0
  sc_path_t path;
533
0
  sc_file_t *dummies[2], *file;
534
0
  int   r, ndummies;
535
536
0
  LOG_FUNC_CALLED(ctx);
537
0
  if (file_ret)
538
0
    *file_ret = NULL;
539
540
  /* Build the CHV path */
541
0
  path = *df_path;
542
0
  if (path.len > SC_MAX_PATH_SIZE - 2) {
543
0
    return SC_ERROR_INVALID_ARGUMENTS;
544
0
  }
545
0
  path.value[path.len++] = ref - 1;
546
0
  path.value[path.len++] = 0;
547
548
  /* See if the CHV already exists */
549
0
  r = sc_select_file(p15card->card, &path, NULL);
550
0
  if (r >= 0)
551
0
    return SC_ERROR_FILE_ALREADY_EXISTS;
552
553
  /* Get the file definition from the profile */
554
0
  if (sc_profile_get_file_by_path(profile, &path, &file) < 0
555
0
      && sc_profile_get_file(profile, (ref == 1)? "CHV1" : "CHV2", &file) < 0
556
0
      && sc_profile_get_file(profile, "CHV", &file) < 0)
557
0
    LOG_TEST_RET(ctx, SC_ERROR_FILE_NOT_FOUND, "profile does not define pin file ACLs");
558
559
0
  file->path = path;
560
0
  file->size = 23;
561
0
  file->id = (ref == 1)? 0x0000 : 0x0100;
562
563
0
  if (unprotected)   {
564
0
    sc_file_add_acl_entry(file, SC_AC_OP_UPDATE,
565
0
        SC_AC_NONE, SC_AC_KEY_REF_NONE);
566
0
  }
567
568
  /* Build the contents of the file */
569
0
  buffer[0] = buffer[1] = buffer[2] = 0xFF;
570
0
  put_pin(profile, buffer + 3, pin, pin_len, pin_tries);
571
0
  put_pin(profile, buffer + 13, puk, puk_len, puk_tries);
572
573
  /* For updating the file, create a dummy CHV files if
574
   * necessary */
575
0
  ndummies = cflex_create_dummy_chvs(profile, p15card,
576
0
        file, SC_AC_OP_UPDATE, dummies);
577
0
  if (ndummies < 0)
578
0
    sc_file_free(file);
579
0
  LOG_TEST_RET(ctx, ndummies, "Unable to create dummy CHV file");
580
581
0
  if (!unprotected)   {
582
0
    struct sc_pin_cmd_data pin_cmd;
583
584
0
    memset(&pin_cmd, 0, sizeof(pin_cmd));
585
0
    pin_cmd.cmd = SC_PIN_CMD_VERIFY;
586
0
    pin_cmd.pin_type = SC_AC_CHV;
587
0
    pin_cmd.pin_reference = ref;
588
0
    pin_cmd.pin1.data = dummy_pin_value;
589
0
    pin_cmd.pin1.len = sizeof(dummy_pin_value);
590
591
0
    r = sc_pin_cmd(p15card->card, &pin_cmd, NULL);
592
0
    if (r < 0)
593
0
      sc_file_free(file);
594
0
    LOG_TEST_RET(ctx, r, "Cannot verify dummy PIN");
595
0
  };
596
597
0
  if (ref == 2)   {
598
    /* Cache dummy SOPIN value */
599
0
    r = sc_pkcs15_find_pin_by_type_and_reference(p15card, NULL, SC_AC_CHV, ref, &pin_obj);
600
0
    if (!r && pin_obj)
601
0
      sc_pkcs15_pincache_add(p15card, pin_obj, dummy_pin_value, sizeof(dummy_pin_value));
602
0
  }
603
604
0
  r = sc_pkcs15init_create_file(profile, p15card, file);
605
0
  if (r < 0)
606
0
    sc_file_free(file);
607
0
  LOG_TEST_RET(ctx, r, "Failed to create PIN file");
608
609
0
  r = sc_update_binary(p15card->card, 0, buffer, 23, 0);
610
0
  if (r < 0 || file_ret == NULL)
611
0
    sc_file_free(file);
612
0
  else
613
0
    *file_ret = file;
614
0
  LOG_TEST_RET(ctx, r, "Failed to update PIN file");
615
616
  /* Delete the dummy CHV files */
617
0
  cflex_delete_dummy_chvs(profile, p15card, ndummies, dummies);
618
619
0
  if (pin_obj)   {
620
    /* Cache new SOPIN value */
621
0
    sc_pkcs15_pincache_add(p15card, pin_obj, pin, pin_len);
622
0
  }
623
624
0
  SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
625
0
}
626
627
/*
628
 * Create a faux pin file
629
 */
630
static int
631
cflex_create_empty_pin_file(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
632
      sc_path_t *path, int ref, sc_file_t **file_ret)
633
0
{
634
0
  int   r;
635
636
0
  LOG_FUNC_CALLED(p15card->card->ctx);
637
0
  *file_ret = NULL;
638
0
  r = cflex_create_pin_file(profile, p15card, path, ref,
639
0
      dummy_pin_value, sizeof(dummy_pin_value), 8,
640
0
      NULL, 0, 0,
641
0
      file_ret, 1);
642
0
  if (r == SC_ERROR_FILE_ALREADY_EXISTS)
643
0
    SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE, r);
644
645
0
  SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE, r);
646
0
}
647
648
/*
649
 * Get private and public key file
650
 */
651
static int cflex_get_keyfiles(sc_profile_t *profile, sc_card_t *card,
652
      const sc_path_t *df_path,
653
      sc_file_t **prkf, sc_file_t **pukf)
654
0
{
655
0
  sc_path_t path = *df_path;
656
0
  int   r;
657
658
0
  if (path.len <= 2) {
659
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
660
0
  }
661
662
  /* Get the private key file */
663
0
  r = sc_profile_get_file_by_path(profile, &path, prkf);
664
0
  if (r < 0) {
665
0
    char pbuf[SC_MAX_PATH_STRING_SIZE];
666
667
0
    r = sc_path_print(pbuf, sizeof(pbuf), &path);
668
0
    if (r != SC_SUCCESS)
669
0
      pbuf[0] = '\0';
670
671
0
    sc_log(card->ctx,  "Cannot find private key file info "
672
0
        "in profile (path=%s).", pbuf);
673
0
    return r;
674
0
  }
675
676
  /* Get the public key file */
677
0
  path.len -= 2;
678
0
  sc_append_file_id(&path, 0x1012);
679
0
  r = sc_profile_get_file_by_path(profile, &path, pukf);
680
0
  if (r < 0) {
681
0
    sc_log(card->ctx,  "Cannot find public key file info in profile.");
682
0
    sc_file_free(*prkf);
683
0
    return r;
684
0
  }
685
686
0
  return 0;
687
0
}
688
689
static void
690
invert_buf(u8 *dest, const u8 *src, size_t c)
691
0
{
692
0
  unsigned int i;
693
694
0
  for (i = 0; i < c; i++)
695
0
    dest[i] = src[c-1-i];
696
0
}
697
698
static int
699
bn2cf(sc_pkcs15_bignum_t *num, u8 *buf, size_t bufsize)
700
0
{
701
0
  size_t  len = num->len;
702
703
0
  if (len > bufsize)
704
0
    return SC_ERROR_INVALID_ARGUMENTS;
705
706
0
  invert_buf(buf, num->data, len);
707
0
  while (len < bufsize)
708
0
    buf[len++] = 0;
709
0
  return 0;
710
0
}
711
712
static int
713
bn2cft(sc_pkcs15_bignum_t *num, u8 tag, u8 *buf, size_t bufsize)
714
0
{
715
0
  size_t  len = num->len;
716
717
0
  if (len + 3 > bufsize)
718
0
    return SC_ERROR_INVALID_ARGUMENTS;
719
0
  memset(buf, 0, bufsize);
720
0
  buf[0] = tag;
721
0
  buf[1] = len + 1;
722
0
  memcpy(buf + 3, num->data, len);
723
0
  return 0;
724
0
}
725
726
/*
727
 * Cryptoflex key encoding
728
 */
729
static int
730
cryptoflex_encode_private_key(sc_profile_t *profile, sc_card_t *card,
731
      struct sc_pkcs15_prkey_rsa *rsa,
732
      u8 *key, size_t *keysize, int key_ref)
733
0
{
734
0
        size_t base = rsa->modulus.len / 2, key_blob_size;
735
0
        int r, key_num = key_ref + 1;
736
737
0
        switch (rsa->modulus.len) {
738
0
  case  512 / 8:
739
0
  case  768 / 8:
740
0
  case 1024 / 8:
741
0
  case 2048 / 8:
742
0
                break;
743
0
  default:
744
0
    return SC_ERROR_INVALID_ARGUMENTS;
745
0
        }
746
747
0
  key_blob_size = 5 * base + 3;
748
0
  if (*keysize < key_blob_size + 3)
749
0
    return SC_ERROR_BUFFER_TOO_SMALL;
750
0
  *keysize = key_blob_size + 3;
751
752
0
        *key++ = key_blob_size >> 8;
753
0
        *key++ = key_blob_size & 0xFF;
754
0
        *key++ = key_num;
755
756
0
  if ((r = bn2cf(&rsa->p,    key + 0 * base, base)) < 0
757
0
   || (r = bn2cf(&rsa->q,    key + 1 * base, base)) < 0
758
0
   || (r = bn2cf(&rsa->iqmp, key + 2 * base, base)) < 0
759
0
   || (r = bn2cf(&rsa->dmp1, key + 3 * base, base)) < 0
760
0
   || (r = bn2cf(&rsa->dmq1, key + 4 * base, base)) < 0)
761
0
    return r;
762
763
0
        key += 5 * base;
764
0
  *key++ = 0;
765
0
  *key++ = 0;
766
0
  *key = 0;
767
768
0
        return 0;
769
0
}
770
771
static int
772
cryptoflex_encode_public_key(sc_profile_t *profile, sc_card_t *card,
773
      struct sc_pkcs15_prkey_rsa *rsa,
774
      u8 *key, size_t *keysize, int key_ref)
775
0
{
776
0
        size_t base;
777
0
        int r, key_num = key_ref + 1;
778
779
0
        switch (rsa->modulus.len) {
780
0
  case  512 / 8:
781
0
  case  768 / 8:
782
0
  case 1024 / 8:
783
0
  case 2048 / 8:
784
0
                break;
785
0
  default:
786
0
    return SC_ERROR_INVALID_ARGUMENTS;
787
0
        }
788
789
0
  base = rsa->modulus.len / 2;
790
0
  if (*keysize < (5 * base + 10))
791
0
    return SC_ERROR_BUFFER_TOO_SMALL;
792
0
  *keysize = 5 * base + 10;
793
794
0
  memset(key, 0, *keysize);
795
0
        *key++ = (5 * base + 7) >> 8;
796
0
        *key++ = (5 * base + 7) & 0xFF;
797
0
        *key++ = key_num;
798
799
  /* Funny code - not sure why we do it this way:
800
   *
801
   * Specs say:   We store: (Length)
802
   *  modulus    modulus  (N bytes)
803
   *  J0 Montgomery const  0    (N/2 bytes)
804
   *  H Montgomery const   0    (N bytes)
805
   *  exponent     exponent 4
806
   *
807
   *        --okir */
808
0
  if ((r = bn2cf(&rsa->modulus,  key + 0 * base, 2 * base)) < 0
809
0
   || (r = bn2cf(&rsa->exponent, key + 5 * base, 4)) < 0)
810
0
    return r;
811
812
0
        return 0;
813
0
}
814
815
/*
816
 * Cyberflex key encoding
817
 */
818
static int
819
cyberflex_encode_private_key(sc_profile_t *profile, sc_card_t *card,
820
      struct sc_pkcs15_prkey_rsa *rsa,
821
      u8 *key, size_t *keysize, int key_ref)
822
0
{
823
0
        size_t base = rsa->modulus.len / 2, key_blob_size, bnlen;
824
0
        int r, key_num = key_ref + 1, alg_id;
825
826
0
        switch (rsa->modulus.len) {
827
0
  case  512 / 8: alg_id = 0xC4; break;
828
0
  case  768 / 8: alg_id = 0xC6; break;
829
0
  case 1024 / 8: alg_id = 0xC8; break;
830
0
  default:
831
0
    return SC_ERROR_INVALID_ARGUMENTS;
832
0
        }
833
834
0
  key_blob_size = 12 + 5 * (base + 3) + 4;
835
0
  if (*keysize < key_blob_size)
836
0
    return SC_ERROR_BUFFER_TOO_SMALL;
837
0
  *keysize = key_blob_size;
838
839
0
  memset(key, 0, *keysize);
840
0
        *key++ = key_blob_size >> 8;
841
0
        *key++ = key_blob_size & 0xFF;
842
0
        *key++ = key_num;
843
0
        *key++ = alg_id;
844
845
  /* key blob header:
846
   * "C2:06:C1:08:13:00:00:05"
847
   */
848
0
  memcpy(key, "\xc2\x06\xc1\x08\x12\x00\x00\x05", 8);
849
0
  key += 8;
850
851
  /* Each bignum is encoded with a 2 byte header and a
852
   * NULL pad byte */
853
0
  bnlen = base + 3;
854
855
0
  if ((r = bn2cft(&rsa->q,    0xC2, key + 0 * bnlen, bnlen)) < 0
856
0
   || (r = bn2cft(&rsa->p,    0xC2, key + 1 * bnlen, bnlen)) < 0
857
0
   || (r = bn2cft(&rsa->iqmp, 0xC2, key + 2 * bnlen, bnlen)) < 0
858
0
   || (r = bn2cft(&rsa->dmq1, 0xC2, key + 3 * bnlen, bnlen)) < 0
859
0
   || (r = bn2cft(&rsa->dmp1, 0xC2, key + 4 * bnlen, bnlen)) < 0)
860
0
    return r;
861
862
0
        key += 5 * bnlen;
863
0
  key[0] = 0x0A;
864
0
  key[1] = 0x0A;
865
0
  key[2] = 0x00;
866
0
  key[3] = 0x00;
867
868
0
        return 0;
869
0
}
870
871
static int
872
cyberflex_encode_public_key(sc_profile_t *profile, sc_card_t *card,
873
      struct sc_pkcs15_prkey_rsa *rsa,
874
      u8 *key, size_t *keysize, int key_ref)
875
0
{
876
0
  size_t base = rsa->modulus.len, key_blob_size, bnlen;
877
0
        int r, key_num = key_ref + 1, alg_id;
878
879
0
        switch (rsa->modulus.len) {
880
0
  case  512 / 8: alg_id = 0xC5; break;
881
0
  case  768 / 8: alg_id = 0xC7; break;
882
0
  case 1024 / 8: alg_id = 0xC9; break;
883
0
  default:
884
0
    return SC_ERROR_INVALID_ARGUMENTS;
885
0
        }
886
887
0
  key_blob_size = 12 + 3 + base + 7 + 4;
888
0
  if (*keysize < key_blob_size)
889
0
    return SC_ERROR_BUFFER_TOO_SMALL;
890
0
  *keysize = key_blob_size;
891
892
0
  memset(key, 0, *keysize);
893
0
        *key++ = key_blob_size >> 8;
894
0
        *key++ = key_blob_size & 0xFF;
895
0
        *key++ = key_num;
896
0
  *key++ = alg_id;
897
898
  /* Key blob header */
899
0
  memcpy(key, "\xC1\x06\xC0\x08\x13\x00\x00\x05", 8);
900
0
  key += 8;
901
902
0
  bnlen = rsa->modulus.len + 3;
903
0
  if ((r = bn2cft(&rsa->modulus, 0xC0, key, bnlen)) < 0
904
0
   || (r = bn2cft(&rsa->exponent, 0xC0, key + bnlen, 3 + 4)) < 0)
905
0
    return r;
906
907
0
  key += bnlen + 3 + 4;
908
0
  key[0] = 0x0A;
909
0
  key[1] = 0x0A;
910
0
  key[2] = 0x00;
911
0
  key[3] = 0x00;
912
0
        return 0;
913
0
}
914
915
static struct sc_pkcs15init_operations sc_pkcs15init_cryptoflex_operations = {
916
  cflex_erase_card,
917
  cryptoflex_init_card,
918
  cflex_create_dir,
919
  cflex_create_domain,
920
  cflex_select_pin_reference,
921
  cflex_create_pin,
922
  NULL,       /* select_key_reference */
923
  cflex_create_key,
924
  cflex_store_key,
925
  cflex_generate_key,
926
  cryptoflex_encode_private_key,
927
  cryptoflex_encode_public_key,
928
  NULL,       /* finalize_card */
929
  NULL,         /* delete_object */
930
  NULL, NULL, NULL, NULL, NULL,   /* pkcs15init emulation */
931
  NULL        /* sanity_check */
932
};
933
934
static struct sc_pkcs15init_operations sc_pkcs15init_cyberflex_operations = {
935
  cflex_erase_card,
936
  NULL,       /* init_card */
937
  cflex_create_dir,
938
  cflex_create_domain,
939
  cflex_select_pin_reference,
940
  cflex_create_pin,
941
  NULL,       /* select_key_reference */
942
  cflex_create_key,
943
  cflex_store_key,
944
  cflex_generate_key,
945
  cyberflex_encode_private_key,
946
  cyberflex_encode_public_key,
947
  NULL,       /* finalize_card */
948
  NULL,         /* delete_object */
949
  NULL, NULL, NULL, NULL, NULL,   /* pkcs15init emulation */
950
  NULL        /* sanity_check */
951
};
952
953
struct sc_pkcs15init_operations *
954
sc_pkcs15init_get_cryptoflex_ops(void)
955
0
{
956
0
  return &sc_pkcs15init_cryptoflex_operations;
957
0
}
958
959
struct sc_pkcs15init_operations *
960
sc_pkcs15init_get_cyberflex_ops(void)
961
0
{
962
0
  return &sc_pkcs15init_cyberflex_operations;
963
0
}