Coverage Report

Created: 2026-10-17 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/pkcs15init/pkcs15-sc-hsm.c
Line
Count
Source
1
/*
2
 * pkcs15-sc-hsm.c : PKCS#15 emulation for write support
3
 *
4
 * Copyright (C) 2012 Andreas Schwier, CardContact, Minden, Germany
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
#ifdef HAVE_CONFIG_H
22
#include <config.h>
23
#endif
24
25
#include <stdlib.h>
26
#include <string.h>
27
#include <sys/types.h>
28
#include <ctype.h>
29
#include <errno.h>
30
#include <stdio.h>
31
32
#include "../libopensc/opensc.h"
33
#include "../libopensc/cardctl.h"
34
#include "../libopensc/log.h"
35
#include "../libopensc/pkcs15.h"
36
#include "../libopensc/cards.h"
37
#include "../libopensc/card-sc-hsm.h"
38
#include "../libopensc/asn1.h"
39
#include "../libopensc/pkcs15.h"
40
41
#include "common/compat_strlcpy.h"
42
#include "common/compat_strlcat.h"
43
44
#include "pkcs15-init.h"
45
#include "profile.h"
46
47
48
49
static u8 pubexp[] = { 0x01, 0x00, 0x01 };
50
51
52
53
static int sc_hsm_delete_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id)
54
0
{
55
0
  sc_card_t *card = p15card->card;
56
0
  sc_path_t path;
57
0
  u8 fid[2];
58
0
  int r;
59
60
0
  fid[0] = prefix;
61
0
  fid[1] = id;
62
63
0
  sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, -1);
64
65
0
  r = sc_delete_file(card, &path);
66
0
  LOG_TEST_RET(card->ctx, r, "Could not delete file");
67
68
0
  LOG_FUNC_RETURN(card->ctx, r);
69
0
}
70
71
72
73
static int sc_hsm_update_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id, int erase, u8 *buf, size_t buflen)
74
0
{
75
0
  sc_card_t *card = p15card->card;
76
0
  sc_file_t *file = NULL;
77
0
  sc_path_t path;
78
0
  u8 fid[2];
79
0
  int r;
80
81
0
  fid[0] = prefix;
82
0
  fid[1] = id;
83
84
0
  sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, -1);
85
86
0
  r = sc_select_file(card, &path, NULL);
87
88
0
  if ((r == SC_SUCCESS) && erase) {
89
0
    r = sc_delete_file(card, &path);
90
0
    LOG_TEST_RET(card->ctx, r, "Could not delete file");
91
0
    r = SC_ERROR_FILE_NOT_FOUND;
92
0
  }
93
94
0
  if (r == SC_ERROR_FILE_NOT_FOUND) {
95
0
    file = sc_file_new();
96
0
    file->id = (path.value[0] << 8) | path.value[1];
97
0
    file->type = SC_FILE_TYPE_WORKING_EF;
98
0
    file->ef_structure = SC_FILE_EF_TRANSPARENT;
99
0
    file->size = (size_t) 0;
100
0
    file->status = SC_FILE_STATUS_ACTIVATED;
101
0
    r = sc_create_file(card, file);
102
0
    sc_file_free(file);
103
0
    LOG_TEST_RET(card->ctx, r, "Could not create file");
104
0
  }
105
106
0
  r = sc_update_binary(card, 0, buf, buflen, 0);
107
0
  LOG_FUNC_RETURN(card->ctx, r);
108
0
}
109
110
111
112
static int sc_hsm_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
113
  sc_pkcs15_object_t *obj)
114
0
{
115
  // Keys are automatically generated in GENERATE ASYMMETRIC KEY PAIR command
116
0
  LOG_FUNC_CALLED(p15card->card->ctx);
117
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
118
0
}
119
120
121
122
static int sc_hsm_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
123
  sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key)
124
0
{
125
0
  LOG_FUNC_CALLED(p15card->card->ctx);
126
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED);
127
0
}
128
129
130
131
static int sc_hsm_determine_free_id(struct sc_pkcs15_card *p15card, u8 range)
132
0
{
133
0
  struct sc_card *card = p15card->card;
134
0
  u8 filelist[MAX_EXT_APDU_LENGTH];
135
0
  int filelistlength, i, j;
136
137
0
  LOG_FUNC_CALLED(p15card->card->ctx);
138
139
0
  filelistlength = sc_list_files(card, filelist, sizeof(filelist));
140
0
  LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier");
141
142
0
  for (j = 0; j < 256; j++) {
143
0
    for (i = 0; i + 1 < filelistlength; i += 2) {
144
0
      if ((filelist[i] == range) && (filelist[i + 1] == j)) {
145
0
        break;
146
0
      }
147
0
    }
148
0
    if (i >= filelistlength) {
149
0
      LOG_FUNC_RETURN(p15card->card->ctx, j);
150
0
    }
151
0
  }
152
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
153
0
}
154
155
156
157
0
static int sc_hsm_encode_gakp_rsa(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, size_t keysize) {
158
0
  struct sc_object_id rsa15withSHA256 = { { 0,4,0,127,0,7,2,2,2,1,2,-1 } };
159
160
0
  LOG_FUNC_CALLED(p15card->card->ctx);
161
162
0
  cvc->coefficientAorExponentlen = sizeof(pubexp);
163
0
  cvc->coefficientAorExponent = malloc(sizeof(pubexp));
164
0
  if (!cvc->coefficientAorExponent) {
165
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
166
0
  }
167
0
  memcpy(cvc->coefficientAorExponent, pubexp, sizeof(pubexp));
168
169
0
  cvc->pukoid = rsa15withSHA256;
170
0
  cvc->modulusSize = (int)keysize;
171
172
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
173
0
}
174
175
176
177
0
static int sc_hsm_encode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, struct sc_pkcs15_prkey_info *key_info) {
178
0
  struct sc_object_id ecdsaWithSHA256 = { { 0,4,0,127,0,7,2,2,2,2,3,-1 } };
179
0
  struct sc_ec_parameters *ecparams = (struct sc_ec_parameters *)key_info->params.data;
180
0
  struct ec_curve *curve = NULL;
181
0
  u8 *curveoid;
182
0
  int curveoidlen,r;
183
184
0
  LOG_FUNC_CALLED(p15card->card->ctx);
185
186
0
  curveoid = ecparams->der.value;
187
0
  if ((ecparams->der.len < 3) || (*curveoid++ != 0x06)) {
188
0
    sc_log(p15card->card->ctx, "EC_PARAMS does not contain curve object identifier");
189
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_INVALID_DATA);
190
0
  }
191
192
0
  curveoidlen = *curveoid++;
193
194
0
  r = sc_pkcs15emu_sc_hsm_get_curve(&curve, curveoid, curveoidlen);
195
0
  LOG_TEST_RET(p15card->card->ctx, r, "Unsupported named curve");
196
197
0
  cvc->primeOrModuluslen = curve->prime.len;
198
0
  cvc->primeOrModulus = malloc(cvc->primeOrModuluslen);
199
0
  if (!cvc->primeOrModulus) {
200
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
201
0
  }
202
0
  memcpy(cvc->primeOrModulus, curve->prime.value, cvc->primeOrModuluslen);
203
204
0
  cvc->coefficientAorExponentlen = curve->coefficientA.len;
205
0
  cvc->coefficientAorExponent = malloc(cvc->coefficientAorExponentlen);
206
0
  if (!cvc->coefficientAorExponent) {
207
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
208
0
  }
209
0
  memcpy(cvc->coefficientAorExponent, curve->coefficientA.value, cvc->coefficientAorExponentlen);
210
211
0
  cvc->coefficientBlen = curve->coefficientB.len;
212
0
  cvc->coefficientB = malloc(cvc->coefficientBlen);
213
0
  if (!cvc->coefficientB) {
214
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
215
0
  }
216
0
  memcpy(cvc->coefficientB, curve->coefficientB.value, cvc->coefficientBlen);
217
218
0
  cvc->basePointGlen = curve->basePointG.len;
219
0
  cvc->basePointG = malloc(cvc->basePointGlen);
220
0
  if (!cvc->basePointG) {
221
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
222
0
  }
223
0
  memcpy(cvc->basePointG, curve->basePointG.value, cvc->basePointGlen);
224
225
0
  cvc->orderlen = curve->order.len;
226
0
  cvc->order = malloc(cvc->orderlen);
227
0
  if (!cvc->order) {
228
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
229
0
  }
230
0
  memcpy(cvc->order, curve->order.value, cvc->orderlen);
231
232
0
  cvc->cofactorlen = curve->coFactor.len;
233
0
  cvc->cofactor = malloc(cvc->cofactorlen);
234
0
  if (!cvc->cofactor) {
235
0
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
236
0
  }
237
0
  memcpy(cvc->cofactor, curve->coFactor.value, cvc->cofactorlen);
238
239
0
  cvc->pukoid = ecdsaWithSHA256;
240
241
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
242
0
}
243
244
static int
245
sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
246
    struct sc_pkcs15_object *object,
247
    struct sc_pkcs15_pubkey *pubkey)
248
0
{
249
0
  struct sc_card *card = p15card->card;
250
0
  sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data;
251
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
252
0
  sc_cardctl_sc_hsm_keygen_info_t sc_hsm_keyinfo;
253
0
  sc_hsm_keygen_data_t *keygen_data;
254
0
  sc_cvc_t cvc;
255
0
  u8 *cvcbin, *cvcpo;
256
0
  unsigned int cla,tag;
257
0
  size_t taglen, cvclen;
258
0
  u8 gakp[512];
259
0
  int r;
260
261
0
  LOG_FUNC_CALLED(p15card->card->ctx);
262
263
0
  key_info->key_reference = sc_hsm_determine_free_id(p15card, KEY_PREFIX);
264
0
  LOG_TEST_RET(card->ctx, key_info->key_reference, "Could not determine key reference");
265
266
0
  memset(&cvc, 0, sizeof(cvc));
267
268
0
  strlcpy(cvc.car, "UTCA00001", sizeof cvc.car);
269
0
  cvc.carLen = strlen(cvc.car);
270
0
  if (priv->serialno)
271
0
    strlcpy(cvc.chr, priv->serialno, sizeof cvc.chr);
272
0
  strlcat(cvc.chr, "00001", sizeof cvc.chr);
273
0
  cvc.chrLen = strlen(cvc.chr);
274
275
0
  switch(object->type) {
276
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
277
0
    r = sc_hsm_encode_gakp_rsa(p15card, &cvc, key_info->modulus_length);
278
0
    break;
279
0
  case SC_PKCS15_TYPE_PRKEY_EC:
280
0
    r = sc_hsm_encode_gakp_ec(p15card, &cvc, key_info);
281
0
    break;
282
0
  default:
283
0
    r = SC_ERROR_NOT_IMPLEMENTED;
284
0
    break;
285
0
  }
286
0
  if (r != SC_SUCCESS) {
287
0
    sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
288
0
    LOG_TEST_RET(p15card->card->ctx, r, "Could not encode GAKP cdata");
289
0
  }
290
291
0
  r = sc_pkcs15emu_sc_hsm_encode_cvc(p15card, &cvc, &cvcbin, &cvclen);
292
0
  sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
293
0
  LOG_TEST_RET(p15card->card->ctx, r, "Could not encode GAKP cdata");
294
295
0
  cvcpo = cvcbin;
296
0
  sc_asn1_read_tag((const u8 **)&cvcpo, cvclen, &cla, &tag, &taglen);
297
0
  sc_asn1_read_tag((const u8 **)&cvcpo, cvclen, &cla, &tag, &taglen);
298
299
0
  if (taglen > sizeof(gakp)) {
300
0
    r = SC_ERROR_BUFFER_TOO_SMALL;
301
0
    goto out;
302
0
  }
303
304
0
  memcpy(gakp, cvcpo, taglen);
305
0
  cvcpo = gakp + taglen;
306
307
0
  if (key_info->aux_data && key_info->aux_data->type == SC_AUX_DATA_TYPE_PROP_KEY_GEN_PARAM) {
308
0
    keygen_data = (sc_hsm_keygen_data_t *)key_info->aux_data->data.proprietary_key_gen_params;
309
310
0
    if (keygen_data->key_use_counter) {
311
0
      if (taglen + 6 > sizeof(gakp)) {
312
0
        r = SC_ERROR_BUFFER_TOO_SMALL;
313
0
        goto out;
314
0
      }
315
0
      *cvcpo++ = 0x90;
316
0
      *cvcpo++ = 0x04;
317
318
0
      *cvcpo++ = (u8)(keygen_data->key_use_counter >> 24);
319
0
      *cvcpo++ = (u8)(keygen_data->key_use_counter >> 16);
320
0
      *cvcpo++ = (u8)(keygen_data->key_use_counter >> 8);
321
0
      *cvcpo++ = (u8)keygen_data->key_use_counter;
322
0
      taglen += 6;
323
0
    }
324
325
0
    if (keygen_data->key_algorithms) {
326
0
      if (taglen + 2 + keygen_data->key_algorithms_len > sizeof(gakp)) {
327
0
        r = SC_ERROR_BUFFER_TOO_SMALL;
328
0
        goto out;
329
0
      }
330
0
      *cvcpo++ = 0x91;
331
0
      *cvcpo++ = (u8)keygen_data->key_algorithms_len;
332
0
      memcpy(cvcpo, keygen_data->key_algorithms, keygen_data->key_algorithms_len);
333
0
      cvcpo += keygen_data->key_algorithms_len;
334
0
      taglen += 2 + keygen_data->key_algorithms_len;
335
0
    }
336
337
0
    if (keygen_data->key_domain) {
338
0
      if (taglen + 3 > sizeof(gakp)) {
339
0
        r = SC_ERROR_BUFFER_TOO_SMALL;
340
0
        goto out;
341
0
      }
342
0
      *cvcpo++ = 0x92;
343
0
      *cvcpo++ = 0x01;
344
0
      *cvcpo++ = (u8)(keygen_data->key_domain - 1);
345
0
      taglen += 3;
346
0
    }
347
0
  }
348
349
0
  sc_hsm_keyinfo.key_id = key_info->key_reference;
350
0
  sc_hsm_keyinfo.auth_key_id = 0;
351
0
  sc_hsm_keyinfo.gakprequest = gakp;
352
0
  sc_hsm_keyinfo.gakprequest_len = taglen;
353
0
  sc_hsm_keyinfo.gakpresponse = NULL;
354
0
  sc_hsm_keyinfo.gakpresponse_len = 0;
355
356
0
  r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_GENERATE_KEY, &sc_hsm_keyinfo);
357
0
  if (r < 0)
358
0
    goto out;
359
360
361
0
  cvcpo = sc_hsm_keyinfo.gakpresponse;
362
0
  cvclen = sc_hsm_keyinfo.gakpresponse_len;
363
364
0
  r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc);
365
0
  if (r < 0) {
366
0
    sc_log(p15card->card->ctx, "Could not decode GAKP rdata");
367
0
    r = SC_ERROR_OBJECT_NOT_VALID;
368
0
    goto out;
369
0
  }
370
371
0
  r = sc_hsm_update_ef(p15card, EE_CERTIFICATE_PREFIX, key_info->key_reference, 1, sc_hsm_keyinfo.gakpresponse, sc_hsm_keyinfo.gakpresponse_len);
372
0
  if (r < 0) {
373
0
    sc_log(p15card->card->ctx, "Could not save certificate signing request");
374
0
    goto out;
375
0
  }
376
377
0
  if (pubkey != NULL) {
378
0
    sc_pkcs15_erase_pubkey(pubkey);
379
0
    memset(pubkey, 0, sizeof *pubkey);
380
0
    r = sc_pkcs15emu_sc_hsm_get_public_key(p15card->card->ctx, &cvc, pubkey);
381
0
  }
382
383
0
  out:
384
385
0
  sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
386
387
0
  if (cvcbin) {
388
0
    free(cvcbin);
389
0
  }
390
0
  if (sc_hsm_keyinfo.gakpresponse) {
391
0
    free(sc_hsm_keyinfo.gakpresponse);
392
0
  }
393
0
  LOG_FUNC_RETURN(p15card->card->ctx, r);
394
0
}
395
396
397
398
/*
399
 * Certificates with a related private key are stored in the fid range CE00 - CEFF. The
400
 * second byte in the fid matches the key id.
401
 * Certificates without a related private key (e.g. CA certificates) are stored in the fid range
402
 * CA00 - CAFF. The second byte is a free selected id.
403
 */
404
static int sc_hsm_emu_store_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
405
    struct sc_pkcs15_object *object,
406
    struct sc_pkcs15_der *data)
407
408
0
{
409
0
  struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
410
0
  struct sc_pkcs15_object *prkey;
411
0
  sc_path_t path;
412
0
  u8 id[2];
413
0
  int r;
414
415
0
  r = sc_pkcs15_find_object_by_id(p15card, SC_PKCS15_TYPE_PRKEY, &cert_info->id , &prkey);
416
417
0
  if (r == SC_ERROR_OBJECT_NOT_FOUND) {
418
0
    r = sc_hsm_determine_free_id(p15card, CA_CERTIFICATE_PREFIX);
419
0
    LOG_TEST_RET(p15card->card->ctx, r, "Out of identifier to store certificate description");
420
421
0
    id[0] = CA_CERTIFICATE_PREFIX;
422
0
    id[1] = r;
423
0
  } else {
424
0
    LOG_TEST_RET(p15card->card->ctx, r, "Error locating matching private key");
425
426
0
    id[0] = EE_CERTIFICATE_PREFIX;
427
0
    id[1] = ((struct sc_pkcs15_prkey_info *)prkey->data)->key_reference;
428
0
  }
429
430
0
  sc_path_set(&path, SC_PATH_TYPE_FILE_ID, id, 2, 0, -1);
431
0
  cert_info->path = path;
432
433
0
  r = sc_hsm_update_ef(p15card, id[0], id[1], 1, data->value, data->len);
434
0
  return r;
435
0
}
436
437
438
439
static int sc_hsm_emu_delete_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
440
    struct sc_pkcs15_object *object)
441
442
0
{
443
0
  struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
444
445
0
  return sc_hsm_delete_ef(p15card, cert_info->path.value[0], cert_info->path.value[1]);
446
0
}
447
448
449
450
static int sc_hsm_emu_store_binary(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
451
    struct sc_pkcs15_object *object,
452
    struct sc_pkcs15_der *data)
453
454
0
{
455
0
  struct sc_pkcs15_data_info *data_info = (struct sc_pkcs15_data_info *) object->data;
456
0
  sc_path_t path;
457
0
  u8 id[2];
458
0
  int r;
459
460
0
  r = sc_hsm_determine_free_id(p15card, DCOD_PREFIX);
461
0
  LOG_TEST_RET(p15card->card->ctx, r, "Out of identifier to store data description");
462
463
0
  if (object->flags & SC_PKCS15_CO_FLAG_PRIVATE) {
464
0
    id[0] = PROT_DATA_PREFIX;
465
0
  } else {
466
0
    id[0] = DATA_PREFIX;
467
0
  }
468
0
  id[1] = r;
469
470
0
  sc_path_set(&path, SC_PATH_TYPE_FILE_ID, id, 2, 0, -1);
471
0
  data_info->path = path;
472
473
0
  r = sc_hsm_update_ef(p15card, id[0], id[1], 1, data->value, data->len);
474
0
  return r;
475
0
}
476
477
478
479
static int sc_hsm_emu_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
480
    struct sc_pkcs15_object *object,
481
    struct sc_pkcs15_der *data, struct sc_path *path)
482
483
0
{
484
0
  struct sc_context *ctx = p15card->card->ctx;
485
0
  int r;
486
487
0
  LOG_FUNC_CALLED(ctx);
488
489
0
  switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
490
0
  case SC_PKCS15_TYPE_PRKEY:
491
0
  case SC_PKCS15_TYPE_PUBKEY:
492
0
    r = SC_SUCCESS;
493
0
    break;
494
0
  case SC_PKCS15_TYPE_CERT:
495
0
    r = sc_hsm_emu_store_cert(p15card, profile, object, data);
496
0
    break;
497
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
498
0
    r = sc_hsm_emu_store_binary(p15card, profile, object, data);
499
0
    break;
500
0
  default:
501
0
    r = SC_ERROR_NOT_IMPLEMENTED;
502
0
    break;
503
0
  }
504
505
0
  LOG_FUNC_RETURN(ctx, r);
506
0
}
507
508
509
510
static int sc_hsm_emu_delete_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
511
    struct sc_pkcs15_object *object, const struct sc_path *path)
512
0
{
513
0
  struct sc_context *ctx = p15card->card->ctx;
514
0
  int r;
515
516
0
  LOG_FUNC_CALLED(ctx);
517
518
0
  switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
519
0
  case SC_PKCS15_TYPE_PRKEY:
520
0
    r = sc_hsm_delete_ef(p15card, KEY_PREFIX, ((struct sc_pkcs15_prkey_info *)object->data)->key_reference);
521
0
    break;
522
0
  case SC_PKCS15_TYPE_CERT:
523
0
    r = sc_hsm_emu_delete_cert(p15card, profile, object);
524
0
    break;
525
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
526
0
    r = sc_delete_file(p15card->card, path);
527
0
    break;
528
0
  case SC_PKCS15_TYPE_PUBKEY:
529
0
    r = SC_SUCCESS;
530
0
    break;
531
0
  default:
532
0
    r = SC_ERROR_NOT_IMPLEMENTED;
533
0
    break;
534
0
  }
535
536
0
  LOG_FUNC_RETURN(ctx, r);
537
0
}
538
539
540
541
static int sc_hsm_emu_update_prkd(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
542
    struct sc_pkcs15_object *object)
543
0
{
544
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data;
545
0
  u8 *buf;
546
0
  size_t buflen;
547
0
  int r;
548
549
  // Don't save AID in PRKD
550
0
  key_info->path.aid.len = 0;
551
552
0
  r = sc_pkcs15_encode_prkdf_entry(p15card->card->ctx, object, &buf, &buflen);
553
0
  LOG_TEST_RET(p15card->card->ctx, r, "Error encoding PRKD entry");
554
555
0
  r = sc_hsm_update_ef(p15card, PRKD_PREFIX, key_info->key_reference, 0, buf, buflen);
556
0
  free(buf);
557
0
  return r;
558
0
}
559
560
561
562
static int sc_hsm_emu_update_dcod(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
563
    struct sc_pkcs15_object *object)
564
0
{
565
0
  struct sc_pkcs15_data_info *data_info = (struct sc_pkcs15_data_info *) object->data;
566
0
  u8 *buf;
567
0
  size_t buflen;
568
0
  int r;
569
570
0
  r = sc_pkcs15_encode_dodf_entry(p15card->card->ctx, object, &buf, &buflen);
571
0
  LOG_TEST_RET(p15card->card->ctx, r, "Error encoding DCOD entry");
572
573
0
  r = sc_hsm_update_ef(p15card, DCOD_PREFIX, data_info->path.value[data_info->path.len - 1], 0, buf, buflen);
574
0
  free(buf);
575
0
  return r;
576
0
}
577
578
579
580
static int sc_hsm_emu_update_cd(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
581
    struct sc_pkcs15_object *object)
582
0
{
583
0
  struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
584
0
  u8 *buf;
585
0
  size_t buflen;
586
0
  int r;
587
588
0
  if ((cert_info->path.len < 2) ||
589
0
    ((cert_info->path.value[cert_info->path.len - 2]) != CA_CERTIFICATE_PREFIX)) {
590
    // Certificates associated with stored private keys don't get a separate CD entry
591
0
    return SC_SUCCESS;
592
0
  }
593
594
0
  r = sc_pkcs15_encode_cdf_entry(p15card->card->ctx, object, &buf, &buflen);
595
0
  LOG_TEST_RET(p15card->card->ctx, r, "Error encoding CD entry");
596
597
0
  r = sc_hsm_update_ef(p15card, CD_PREFIX, cert_info->path.value[cert_info->path.len - 1], 0, buf, buflen);
598
0
  free(buf);
599
0
  return r;
600
0
}
601
602
603
604
static int sc_hsm_emu_delete_cd(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
605
    struct sc_pkcs15_object *object)
606
0
{
607
0
  struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) object->data;
608
609
0
  if ((cert_info->path.len < 2) ||
610
0
    ((cert_info->path.value[cert_info->path.len - 2]) != CA_CERTIFICATE_PREFIX)) {
611
    // Certificates associated with stored private keys don't get a separate CD entry
612
0
    return SC_SUCCESS;
613
0
  }
614
615
0
  return sc_hsm_delete_ef(p15card, CD_PREFIX, cert_info->path.value[cert_info->path.len - 1]);
616
0
}
617
618
619
620
static int sc_hsm_emu_update_any_df(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
621
    unsigned op, struct sc_pkcs15_object *object)
622
0
{
623
0
  struct sc_context *ctx = p15card->card->ctx;
624
0
  int rv = SC_ERROR_NOT_SUPPORTED;
625
626
0
  SC_FUNC_CALLED(ctx, 1);
627
0
  switch(op)   {
628
0
  case SC_AC_OP_ERASE:
629
0
    sc_log(ctx, "Update DF; erase object('%s',type:%X)", object->label, object->type);
630
0
    switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) {
631
0
    case SC_PKCS15_TYPE_PRKEY:
632
0
      rv = sc_hsm_delete_ef(p15card, PRKD_PREFIX, ((struct sc_pkcs15_prkey_info *)object->data)->key_reference);
633
0
      break;
634
0
    case SC_PKCS15_TYPE_PUBKEY:
635
0
      rv = SC_SUCCESS;
636
0
      break;
637
0
    case SC_PKCS15_TYPE_CERT:
638
0
      rv = sc_hsm_emu_delete_cd(profile, p15card, object);
639
0
      break;
640
0
    case SC_PKCS15_TYPE_DATA_OBJECT:
641
0
      rv = sc_hsm_delete_ef(p15card, DCOD_PREFIX, ((struct sc_pkcs15_data_info *)object->data)->path.value[1]);
642
0
      break;
643
0
    }
644
0
    break;
645
0
  case SC_AC_OP_UPDATE:
646
0
  case SC_AC_OP_CREATE:
647
0
    sc_log(ctx, "Update DF; create object('%s',type:%X)", object->label, object->type);
648
0
    switch(object->type & SC_PKCS15_TYPE_CLASS_MASK) {
649
0
    case SC_PKCS15_TYPE_PUBKEY:
650
0
      rv = SC_SUCCESS;
651
0
      break;
652
0
    case SC_PKCS15_TYPE_PRKEY:
653
0
      rv = sc_hsm_emu_update_prkd(profile, p15card, object);
654
0
      break;
655
0
    case SC_PKCS15_TYPE_CERT:
656
0
      rv = sc_hsm_emu_update_cd(profile, p15card, object);
657
0
      break;
658
0
    case SC_PKCS15_TYPE_DATA_OBJECT:
659
0
      rv = sc_hsm_emu_update_dcod(profile, p15card, object);
660
0
      break;
661
0
    }
662
0
    break;
663
0
  }
664
0
  SC_FUNC_RETURN(ctx, 1, rv);
665
0
}
666
667
static struct sc_pkcs15init_operations
668
    sc_pkcs15init_sc_hsm_operations = {
669
        NULL, /* erase_card */
670
        NULL, /* init_card  */
671
        NULL, /* create_dir */
672
        NULL, /* create_domain */
673
        NULL, /* select_pin_reference */
674
        NULL, /* create_pin */
675
        NULL, /* select key reference */
676
        sc_hsm_create_key,
677
        sc_hsm_store_key,
678
        sc_hsm_generate_key,
679
        NULL,       /* encode private key */
680
        NULL,       /* encode public key */
681
        NULL,       /* finalize_card */
682
        sc_hsm_emu_delete_object, /* delete object */
683
        NULL,       /* pkcs15init emulation update_dir */
684
        sc_hsm_emu_update_any_df, /* pkcs15init emulation update_any_df */
685
        NULL,       /* pkcs15init emulation update_tokeninfo */
686
        NULL,       /* pkcs15init emulation write_info */
687
        sc_hsm_emu_store_data,
688
        NULL, /* sanity_check */
689
};
690
691
struct sc_pkcs15init_operations *
692
sc_pkcs15init_get_sc_hsm_ops(void)
693
0
{
694
0
  return &sc_pkcs15init_sc_hsm_operations;
695
0
}
696