Coverage Report

Created: 2025-09-04 06:45

/src/opensc/src/libopensc/pkcs15-idprime.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * partial PKCS15 emulation for IDPrime cards.
3
 *
4
 * We can not use the ISO code, since the EF.DIR and EF.ATR for
5
 * object discovery are missing
6
 *
7
 * Copyright (C) 2019, Red Hat, Inc.
8
 *
9
 * Author: Jakub Jelen <jjelen@redhat.com>
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 */
24
25
#ifdef HAVE_CONFIG_H
26
#include "config.h"
27
#endif
28
29
#include <string.h>
30
#include <stdlib.h>
31
#include "internal.h"
32
#include "cardctl.h"
33
#include "pkcs15.h"
34
35
0
#define CERT_LABEL_TEMPLATE "Certificate %d"
36
0
#define PUBKEY_LABEL_TEMPLATE "Public key %d"
37
0
#define PRIVKEY_LABEL_TEMPLATE "Private key %d"
38
39
static int idprime_detect_card(sc_pkcs15_card_t *p15card)
40
2
{
41
2
  sc_card_t *card = p15card->card;
42
43
2
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
44
45
2
  if (card->type < SC_CARD_TYPE_IDPRIME_BASE
46
2
    || card->type >= SC_CARD_TYPE_IDPRIME_BASE+1000)
47
2
    return SC_ERROR_INVALID_CARD;
48
0
  return SC_SUCCESS;
49
2
}
50
51
static int sc_pkcs15emu_idprime_init(sc_pkcs15_card_t *p15card)
52
0
{
53
0
  int r, i;
54
0
  sc_card_t *card = p15card->card;
55
0
  sc_serial_number_t serial;
56
0
  char buf[SC_MAX_SERIALNR * 2 + 1];
57
0
  int count;
58
0
  char *token_name = NULL;
59
0
  struct sc_pkcs15_auth_info pin_info;
60
0
  struct sc_pkcs15_object   pin_obj;
61
0
  const char pin_label[] = "PIN";
62
0
  const char *pin_id = "11";
63
0
  const char sig_pin_label[] = "Digital Signature PIN";
64
0
  const char *sig_pin_id = "83";
65
66
  /* oid for key usage */
67
0
  static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }};
68
0
  unsigned int usage;
69
70
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
71
72
  /* could read this off card if needed */
73
0
  set_string(&p15card->tokeninfo->label, "IDPrime");
74
0
  set_string(&p15card->tokeninfo->manufacturer_id, "Gemalto");
75
76
  /*
77
   * get serial number
78
   */
79
0
  memset(&serial, 0, sizeof(serial));
80
0
  r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
81
0
  if (r < 0) {
82
0
    sc_log(card->ctx, "sc_card_ctl rc=%d", r);
83
0
    set_string(&p15card->tokeninfo->serial_number, "00000000");
84
0
  } else {
85
0
    sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
86
0
    set_string(&p15card->tokeninfo->serial_number, buf);
87
0
  }
88
  /* set pin */
89
0
  sc_log(card->ctx,  "IDPrime adding pin...");
90
0
  memset(&pin_info, 0, sizeof(pin_info));
91
0
  memset(&pin_obj,  0, sizeof(pin_obj));
92
93
0
  pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
94
0
  sc_pkcs15_format_id(pin_id, &pin_info.auth_id);
95
0
  pin_info.attrs.pin.reference     = 0x11;
96
0
  pin_info.attrs.pin.flags         = SC_PKCS15_PIN_FLAG_INITIALIZED;
97
0
  pin_info.attrs.pin.type          = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
98
0
  pin_info.attrs.pin.min_length    = 4;
99
0
  pin_info.attrs.pin.stored_length = 0;
100
0
  pin_info.attrs.pin.max_length    = 16;
101
0
  pin_info.tries_left    = -1;
102
103
0
  if (card->type == SC_CARD_TYPE_IDPRIME_840
104
0
      || card->type == SC_CARD_TYPE_IDPRIME_940
105
0
      || card->type == SC_CARD_TYPE_IDPRIME_GENERIC) {
106
0
    pin_info.attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
107
0
    pin_info.attrs.pin.stored_length = 16;
108
0
    pin_info.attrs.pin.pad_char = 0x00;
109
0
  }
110
111
0
  sc_log(card->ctx,  "IDPrime Adding pin with label=%s", pin_label);
112
0
  strncpy(pin_obj.label, pin_label, SC_PKCS15_MAX_LABEL_SIZE - 1);
113
0
  pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
114
115
0
  r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
116
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not add pin object");
117
118
  /* set signature pin for 940 cards */
119
0
  if (card->type == SC_CARD_TYPE_IDPRIME_940) {
120
0
    sc_log(card->ctx,  "IDPrime adding Digital Signature pin...");
121
0
    memset(&pin_info, 0, sizeof(pin_info));
122
0
    memset(&pin_obj,  0, sizeof(pin_obj));
123
124
0
    pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
125
0
    sc_pkcs15_format_id(sig_pin_id, &pin_info.auth_id);
126
0
    pin_info.attrs.pin.reference     = 0x83;
127
0
    pin_info.attrs.pin.flags         = SC_PKCS15_PIN_FLAG_INITIALIZED;
128
0
    pin_info.attrs.pin.type          = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
129
0
    pin_info.attrs.pin.min_length    = 4;
130
0
    pin_info.attrs.pin.stored_length = 0;
131
0
    pin_info.attrs.pin.max_length    = 16;
132
0
    pin_info.tries_left    = -1;
133
134
0
    pin_info.attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING;
135
0
    pin_info.attrs.pin.stored_length = 16;
136
0
    pin_info.attrs.pin.pad_char = 0x00;
137
138
0
    sc_log(card->ctx,  "IDPrime Adding Digital Signature pin with label=%s", sig_pin_label);
139
0
    strncpy(pin_obj.label, sig_pin_label, SC_PKCS15_MAX_LABEL_SIZE - 1);
140
0
    pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
141
142
0
    r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
143
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not add Digital Signature pin object");
144
0
  }
145
146
  /*
147
   * get token name if provided
148
   */
149
0
  r = sc_card_ctl(card, SC_CARDCTL_IDPRIME_GET_TOKEN_NAME, &token_name);
150
0
  if (r < 0) {
151
    /* On failure we will get the token name from certificates later */
152
0
    sc_log(card->ctx, "sc_card_ctl rc=%d", r);
153
0
  } else {
154
0
    free(p15card->tokeninfo->label);
155
0
    p15card->tokeninfo->label = token_name;
156
0
    sc_log(card->ctx,  "IDPrime setting token label = %s", token_name);
157
0
  }
158
  /*
159
   * certs, pubkeys and priv keys are related and we assume
160
   * they are in order
161
   * We need to read the cert, get modulus and keylen
162
   * We use those for the pubkey, and priv key objects.
163
   */
164
0
  sc_log(card->ctx,  "IDPrime adding certs, pub and priv keys...");
165
0
  r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_INIT_GET_OBJECTS, &count);
166
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not initiate cert objects.");
167
168
0
  for (i = 0; i < count; i++) {
169
0
    struct sc_pkcs15_prkey_info prkey_info;
170
0
    struct sc_pkcs15_cert_info cert_info;
171
0
    struct sc_pkcs15_pubkey_info pubkey_info;
172
0
    struct sc_pkcs15_object cert_obj;
173
0
    struct sc_pkcs15_object pubkey_obj;
174
0
    struct sc_pkcs15_object prkey_obj;
175
0
    sc_pkcs15_der_t cert_der;
176
0
    sc_pkcs15_cert_t *cert_out = NULL;
177
0
    const char *pin_id = NULL;
178
179
0
    r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_GET_PIN_ID, (void *) &pin_id);
180
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not get PIN id of next object ");
181
0
    r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_GET_NEXT_OBJECT, &prkey_info);
182
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not get next object");
183
184
0
    memset(&cert_info, 0, sizeof(cert_info));
185
0
    memset(&pubkey_info, 0, sizeof(pubkey_info));
186
    /* prkey_info cleaned by the card_ctl call */
187
0
    memset(&cert_obj,  0, sizeof(cert_obj));
188
0
    memset(&pubkey_obj,  0, sizeof(pubkey_obj));
189
0
    memset(&prkey_obj,  0, sizeof(prkey_obj));
190
191
0
    cert_info.id = prkey_info.id;
192
0
    pubkey_info.id = prkey_info.id;
193
0
    cert_info.path = prkey_info.path;
194
    /* For private keys, we no longer care for the path, just
195
     * the key reference later used in the security environment */
196
0
    prkey_info.path.len = 0;
197
0
    prkey_info.path.aid.len = 0;
198
0
    pubkey_info.key_reference = prkey_info.key_reference;
199
0
    sc_log(card->ctx,  "Key ref r=%x", prkey_info.key_reference);
200
201
0
    pubkey_info.native        = 1;
202
0
    prkey_info.native        = 1;
203
204
0
    snprintf(cert_obj.label, SC_PKCS15_MAX_LABEL_SIZE, CERT_LABEL_TEMPLATE, i+1);
205
0
    snprintf(pubkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PUBKEY_LABEL_TEMPLATE, i+1);
206
0
    snprintf(prkey_obj.label, SC_PKCS15_MAX_LABEL_SIZE, PRIVKEY_LABEL_TEMPLATE, i+1);
207
0
    prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
208
209
    /* Differentiate between objects accessible with normal and with digital signature pin */
210
0
    sc_pkcs15_format_id(pin_id, &prkey_obj.auth_id);
211
0
    sc_log(card->ctx,  "Pin ID r=%s", pin_id);
212
213
0
    if (memcmp(pin_id, sig_pin_id, 2) == 0)
214
0
      prkey_obj.user_consent = 1;
215
216
0
    r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, 0);
217
218
0
    if (r) {
219
0
      sc_log(card->ctx,  "No cert found,i=%d", i);
220
0
      continue;
221
0
    }
222
0
    cert_info.path.count = (int)cert_der.len;
223
224
0
    sc_log(card->ctx,
225
0
       "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n",
226
0
       cert_der.len, cert_info.path.count, r);
227
0
    sc_log_hex(card->ctx, "cert", cert_der.value, cert_der.len);
228
229
    /* cache it using the PKCS15 emulation objects */
230
    /* as it does not change */
231
0
    if (cert_der.value) {
232
0
      cert_info.value.value = cert_der.value;
233
0
      cert_info.value.len = cert_der.len;
234
0
      cert_info.path.len = 0; /* use in mem cert from now on */
235
0
    }
236
237
    /* following will find the cached cert in cert_info */
238
0
    r =  sc_pkcs15_read_certificate(p15card, &cert_info, 0, &cert_out);
239
0
    if (r < 0 || cert_out->key == NULL) {
240
0
      sc_log(card->ctx,  "Failed to read/parse the certificate r=%d",r);
241
0
      if (cert_out != NULL)
242
0
        sc_pkcs15_free_certificate(cert_out);
243
0
      free(cert_der.value);
244
0
      continue;
245
0
    }
246
247
0
    r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
248
0
    if (r < 0) {
249
0
      sc_log(card->ctx,  " Failed to add cert obj r=%d",r);
250
0
      sc_pkcs15_free_certificate(cert_out);
251
0
      free(cert_der.value);
252
0
      continue;
253
0
    }
254
    /* set the token name to the name of the CN of the first certificate */
255
0
    if (!token_name) {
256
0
      u8 * cn_name = NULL;
257
0
      size_t cn_len = 0;
258
0
      static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }};
259
0
      r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject,
260
0
        cert_out->subject_len, &cn_oid, &cn_name, &cn_len);
261
0
      if (r == SC_SUCCESS) {
262
0
        token_name = malloc (cn_len+1);
263
0
        if (!token_name) {
264
0
          free(cn_name);
265
0
          r = SC_ERROR_OUT_OF_MEMORY;
266
0
          goto fail;
267
0
        }
268
0
        memcpy(token_name, cn_name, cn_len);
269
0
        free(cn_name);
270
0
        token_name[cn_len] = '\0';
271
0
        free(p15card->tokeninfo->label);
272
0
        p15card->tokeninfo->label = token_name;
273
0
      }
274
0
    }
275
276
277
0
    r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key,
278
0
      &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len);
279
0
    if (r < 0)
280
0
      goto fail;
281
0
    pubkey_obj.emulated = cert_out->key;
282
283
0
    r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL);
284
0
    if (r < 0) {
285
0
      usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */
286
0
    }
287
0
    sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1);
288
0
    sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n",
289
0
      sc_dump_hex(cert_info.id.value, cert_info.id.len),
290
0
      usage, pubkey_info.usage, prkey_info.usage);
291
292
0
    if (cert_out->key->algorithm == SC_ALGORITHM_RSA) {
293
0
      pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8;
294
0
      prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8;
295
0
      sc_log(card->ctx, "adding rsa public key r=%d usage=%x", r, pubkey_info.usage);
296
0
      r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
297
0
      if (r < 0) {
298
0
        free(pubkey_info.direct.spki.value);
299
0
        goto fail;
300
0
      }
301
0
      pubkey_info.direct.spki.value = NULL; /* moved to the pubkey object on p15card  */
302
0
      pubkey_info.direct.spki.len = 0;
303
0
      if (prkey_info.key_reference >= 0) {
304
0
        sc_log(card->ctx, "adding rsa private key r=%d usage=%x", r, prkey_info.usage);
305
0
        r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
306
0
      } else {
307
0
        sc_log(card->ctx, "missing rsa private key r=%d usage=%x", r, prkey_info.usage);
308
0
      }
309
0
      if (r < 0)
310
0
        goto fail;
311
0
    } else if (cert_out->key->algorithm == SC_ALGORITHM_EC) {
312
0
      pubkey_info.field_length = cert_out->key->u.ec.params.field_length;
313
0
      prkey_info.field_length = cert_out->key->u.ec.params.field_length;
314
0
      sc_log(card->ctx, "adding ec public key r=%d usage=%x", r, pubkey_info.usage);
315
0
      r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info);
316
0
      if (r < 0) {
317
0
        free(pubkey_info.direct.spki.value);
318
0
        goto fail;
319
0
      }
320
0
      pubkey_info.direct.spki.value = NULL;
321
0
      pubkey_info.direct.spki.len = 0;
322
0
      if (prkey_info.key_reference >= 0) {
323
0
        sc_log(card->ctx, "adding ec private key r=%d usage=%x", r, prkey_info.usage);
324
0
        r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info);
325
0
      } else {
326
0
        sc_log(card->ctx, "missing ec private key r=%d usage=%x", r, prkey_info.usage);
327
0
      }
328
0
      if (r < 0)
329
0
        goto fail;
330
0
    } else {
331
0
      sc_log(card->ctx, "unsupported key.algorithm %lu", cert_out->key->algorithm);
332
0
      sc_pkcs15_free_certificate(cert_out);
333
0
      free(pubkey_info.direct.spki.value);
334
0
      continue;
335
0
    }
336
337
0
    cert_out->key = NULL;
338
0
fail:
339
0
    sc_pkcs15_free_certificate(cert_out);
340
0
    if (r < 0) {
341
0
      (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, &count);
342
0
      LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to add object.");
343
0
    }
344
345
0
  }
346
0
  r = (card->ops->card_ctl)(card, SC_CARDCTL_IDPRIME_FINAL_GET_OBJECTS, &count);
347
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not finalize cert objects.");
348
349
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
350
351
0
err:
352
0
  sc_pkcs15_card_clear(p15card);
353
0
  LOG_FUNC_RETURN(card->ctx, r);
354
0
}
355
356
int sc_pkcs15emu_idprime_init_ex(sc_pkcs15_card_t *p15card,
357
    struct sc_aid *aid)
358
2
{
359
2
  sc_card_t   *card = p15card->card;
360
2
  sc_context_t    *ctx = card->ctx;
361
362
2
  LOG_FUNC_CALLED(ctx);
363
364
2
  if (idprime_detect_card(p15card))
365
2
    return SC_ERROR_WRONG_CARD;
366
0
  return sc_pkcs15emu_idprime_init(p15card);
367
2
}