Coverage Report

Created: 2025-11-23 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-cac.c
Line
Count
Source
1
/*
2
 * partial PKCS15 emulation for CAC-II cards
3
 * only minimal use of the authentication cert and key
4
 *
5
 * Copyright (C) 2005,2006,2007,2008,2009,2010
6
 *               Douglas E. Engert <deengert@anl.gov>
7
 *               2004, Nils Larsch <larsch@trustcenter.de>
8
 * Copyright (C) 2006, Identity Alliance,
9
 *               Thomas Harning <thomas.harning@identityalliance.com>
10
 * Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
11
 * Copyright (C) 2016, Red Hat, Inc.
12
 *
13
 * CAC driver author: Robert Relyea <rrelyea@redhat.com>
14
 *
15
 * This library is free software; you can redistribute it and/or
16
 * modify it under the terms of the GNU Lesser General Public
17
 * License as published by the Free Software Foundation; either
18
 * version 2.1 of the License, or (at your option) any later version.
19
 *
20
 * This library is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23
 * Lesser General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Lesser General Public
26
 * License along with this library; if not, write to the Free Software
27
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28
 */
29
30
#ifdef HAVE_CONFIG_H
31
#include "config.h"
32
#endif
33
34
#include <stdlib.h>
35
#include <string.h>
36
#include <stdio.h>
37
#include <ctype.h>
38
39
#include "internal.h"
40
#include "cardctl.h"
41
#include "pkcs15.h"
42
/* X509 Key Usage flags */
43
#include "../pkcs15init/pkcs15-init.h"
44
45
/* probably should get manufacturer ID from cuid */
46
4.19k
#define MANU_ID   "Common Access Card"
47
48
49
typedef struct pdata_st {
50
  const char *id;
51
  const char *label;
52
  const char *path;
53
  int         ref;
54
  int         type;
55
  unsigned int maxlen;
56
  unsigned int minlen;
57
  unsigned int storedlen;
58
  int         flags;
59
  int         tries_left;
60
  const unsigned char  pad_char;
61
  int         obj_flags;
62
} pindata;
63
64
static int cac_detect_card(sc_pkcs15_card_t *p15card)
65
56.2k
{
66
56.2k
  sc_card_t *card = p15card->card;
67
68
56.2k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
69
56.2k
  if (card->type < SC_CARD_TYPE_CAC_GENERIC
70
6.83k
    || card->type >= SC_CARD_TYPE_CAC_GENERIC+1000)
71
52.0k
    return SC_ERROR_INVALID_CARD;
72
4.19k
  return SC_SUCCESS;
73
56.2k
}
74
75
#define CAC_NUM_CERTS_AND_KEYS 10
76
77
static const char * cac_get_name(int type)
78
4.19k
{
79
4.19k
    switch (type) {
80
724
    case SC_CARD_TYPE_CAC_I: return ("CAC I");
81
1.74k
    case SC_CARD_TYPE_CAC_II: return ("CAC II");
82
1.73k
    case SC_CARD_TYPE_CAC_ALT_HID: return ("CAC ALT HID");
83
0
    default: break;
84
4.19k
    }
85
0
    return ("CAC");
86
4.19k
}
87
88
static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card)
89
4.19k
{
90
4.19k
  static const pindata pins[] = {
91
4.19k
    { "1", "PIN", "", 0x00,
92
4.19k
      SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
93
4.19k
      8, 4, 8,
94
4.19k
      SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
95
4.19k
      SC_PKCS15_PIN_FLAG_INITIALIZED ,
96
4.19k
      -1, 0xFF,
97
4.19k
      SC_PKCS15_CO_FLAG_PRIVATE },
98
4.19k
    { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
99
4.19k
  };
100
  /* oid for key usage */
101
4.19k
  static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }};
102
4.19k
  unsigned int usage;
103
104
105
  /*
106
   * The size of the key or the algid is not really known
107
   * but can be derived from the certificates.
108
   * the cert, pubkey and privkey are a set.
109
   * Key usages bits taken from certificate key usage extension.
110
   */
111
112
4.19k
  int    r, i;
113
4.19k
  sc_card_t *card = p15card->card;
114
4.19k
  sc_serial_number_t serial;
115
4.19k
  char buf[SC_MAX_SERIALNR * 2 + 1];
116
4.19k
  int count;
117
4.19k
  char *token_name = NULL;
118
119
120
4.19k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
121
122
4.19k
  memset(&serial, 0, sizeof(serial));
123
124
  /* could read this off card if needed */
125
126
4.19k
  set_string(&p15card->tokeninfo->label, cac_get_name(card->type));
127
4.19k
  set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID);
128
129
  /*
130
   * get serial number
131
   */
132
4.19k
  r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
133
4.19k
  if (r < 0) {
134
3.23k
    sc_log(card->ctx, "sc_card_ctl rc=%d",r);
135
3.23k
    set_string(&p15card->tokeninfo->serial_number, "00000000");
136
3.23k
  } else {
137
967
    sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
138
967
    set_string(&p15card->tokeninfo->serial_number, buf);
139
967
  }
140
141
  /* set pins */
142
  /* TODO we should not create PIN objects if it is not initialized
143
   * (opensc-tool -s 0020000000 returns 0x6A 0x88)
144
   */
145
4.19k
  sc_log(card->ctx,  "CAC adding pins...");
146
8.39k
  for (i = 0; pins[i].id; i++) {
147
4.19k
    struct sc_pkcs15_auth_info pin_info;
148
4.19k
    struct sc_pkcs15_object   pin_obj;
149
4.19k
    const char * label;
150
151
4.19k
    memset(&pin_info, 0, sizeof(pin_info));
152
4.19k
    memset(&pin_obj,  0, sizeof(pin_obj));
153
154
4.19k
    pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
155
4.19k
    sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
156
4.19k
    pin_info.attrs.pin.reference     = pins[i].ref;
157
4.19k
    pin_info.attrs.pin.flags         = pins[i].flags;
158
4.19k
    pin_info.attrs.pin.type          = pins[i].type;
159
4.19k
    pin_info.attrs.pin.min_length    = pins[i].minlen;
160
4.19k
    pin_info.attrs.pin.stored_length = pins[i].storedlen;
161
4.19k
    pin_info.attrs.pin.max_length    = pins[i].maxlen;
162
4.19k
    pin_info.attrs.pin.pad_char      = pins[i].pad_char;
163
4.19k
    sc_format_path(pins[i].path, &pin_info.path);
164
4.19k
    pin_info.tries_left    = -1;
165
166
4.19k
    label = pins[i].label;
167
4.19k
    sc_log(card->ctx,  "CAC Adding pin %d label=%s",i, label);
168
4.19k
    strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1);
169
4.19k
    pin_obj.flags = pins[i].obj_flags;
170
171
    /* get the ACA path in case it needs to be selected before PIN verify */
172
4.19k
    r = sc_card_ctl(card, SC_CARDCTL_CAC_GET_ACA_PATH, &pin_info.path);
173
4.19k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not get ACA path.");
174
175
4.19k
    r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
176
4.19k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not add pin object.");
177
4.19k
  }
178
179
  /* set other objects */
180
4.19k
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_GENERIC_OBJECTS, &count);
181
4.19k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not initiate generic objects.");
182
183
20.6k
  for (i = 0; i < count; i++) {
184
16.4k
    struct sc_pkcs15_data_info obj_info;
185
16.4k
    struct sc_pkcs15_object    obj_obj;
186
187
16.4k
    r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_GENERIC_OBJECT, &obj_info);
188
16.4k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not get next generic object.");
189
16.4k
    memset(&obj_obj, 0, sizeof(obj_obj));
190
16.4k
    memcpy(obj_obj.label, obj_info.app_label, sizeof(obj_obj.label));
191
192
16.4k
    r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
193
16.4k
      &obj_obj, &obj_info);
194
16.4k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not finalize generic object.");
195
16.4k
  }
196
4.19k
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS, &count);
197
4.19k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not finalize generic objects.");
198
199
  /*
200
   * certs, pubkeys and priv keys are related and we assume
201
   * they are in order
202
   * We need to read the cert, get modulus and keylen
203
   * We use those for the pubkey, and priv key objects.
204
   */
205
4.19k
  sc_log(card->ctx,  "CAC adding certs, pub and priv keys...");
206
4.19k
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_CERT_OBJECTS, &count);
207
4.19k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not initiate cert objects.");
208
209
17.5k
  for (i = 0; i < count; i++) {
210
13.3k
    struct sc_pkcs15_data_info obj_info;
211
13.3k
    struct sc_pkcs15_cert_info cert_info;
212
13.3k
    struct sc_pkcs15_pubkey_info pubkey_info;
213
13.3k
    struct sc_pkcs15_prkey_info prkey_info;
214
13.3k
    struct sc_pkcs15_object cert_obj;
215
13.3k
    struct sc_pkcs15_object pubkey_obj;
216
13.3k
    struct sc_pkcs15_object prkey_obj;
217
13.3k
    sc_pkcs15_der_t   cert_der;
218
13.3k
    sc_pkcs15_cert_t *cert_out = NULL;
219
220
13.3k
    r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT, &obj_info);
221
13.3k
    LOG_TEST_RET(card->ctx, r, "Can not get next object");
222
223
13.3k
    memset(&cert_info, 0, sizeof(cert_info));
224
13.3k
    memset(&pubkey_info, 0, sizeof(pubkey_info));
225
13.3k
    memset(&prkey_info, 0, sizeof(prkey_info));
226
13.3k
    memset(&cert_obj,  0, sizeof(cert_obj));
227
13.3k
    memset(&pubkey_obj,  0, sizeof(pubkey_obj));
228
13.3k
    memset(&prkey_obj,  0, sizeof(prkey_obj));
229
230
13.3k
    cert_info.id = obj_info.id;
231
13.3k
    pubkey_info.id = obj_info.id;
232
13.3k
    prkey_info.id = obj_info.id;
233
13.3k
    cert_info.path = obj_info.path;
234
13.3k
    prkey_info.path = obj_info.path;
235
    /* Add 0x3f00 to the front of prkey_info.path to make sc_key_file happy */
236
    /* only do this if our path.len is 1 or 2 */
237
13.3k
    if (prkey_info.path.len && prkey_info.path.len <= 2) {
238
4.79k
      prkey_info.path.value[2] = prkey_info.path.value[0];
239
4.79k
      prkey_info.path.value[3] = prkey_info.path.value[1];
240
4.79k
      prkey_info.path.value[0] = 0x3f;
241
4.79k
      prkey_info.path.value[1] = 0x00;
242
4.79k
      prkey_info.path.len += 2;
243
4.79k
    }
244
13.3k
    pubkey_info.native        = 1;
245
13.3k
    pubkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1];
246
13.3k
    prkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1];
247
13.3k
    prkey_info.native        = 1;
248
249
13.3k
    memcpy(cert_obj.label, obj_info.app_label, sizeof(obj_info.app_label));
250
13.3k
    memcpy(pubkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label));
251
13.3k
    memcpy(prkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label));
252
13.3k
    prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
253
13.3k
    sc_pkcs15_format_id(pins[0].id, &prkey_obj.auth_id);
254
255
13.3k
    r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, 0);
256
257
13.3k
    if (r) {
258
11.3k
      sc_log(card->ctx,  "No cert found,i=%d", i);
259
11.3k
      continue;
260
11.3k
    }
261
1.98k
    cert_info.path.count = (int)cert_der.len;
262
263
1.98k
    sc_log(card->ctx,
264
1.98k
       "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n",
265
1.98k
       cert_der.len, cert_info.path.count, r);
266
1.98k
    sc_log_hex(card->ctx, "cert", cert_der.value, cert_der.len);
267
268
    /* cache it using the PKCS15 emulation objects */
269
    /* as it does not change */
270
1.98k
    if (cert_der.value) {
271
1.09k
      cert_info.value.value = cert_der.value;
272
1.09k
      cert_info.value.len = cert_der.len;
273
1.09k
      cert_info.path.len = 0; /* use in mem cert from now on */
274
1.09k
    }
275
276
    /* following will find the cached cert in cert_info */
277
1.98k
    r =  sc_pkcs15_read_certificate(p15card, &cert_info, 0, &cert_out);
278
1.98k
    if (r < 0 || cert_out->key == NULL) {
279
1.62k
      sc_log(card->ctx,  "Failed to read/parse the certificate r=%d",r);
280
1.62k
      if (cert_out != NULL)
281
0
        sc_pkcs15_free_certificate(cert_out);
282
1.62k
      free(cert_info.value.value);
283
1.62k
      continue;
284
1.62k
    }
285
286
361
    r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
287
361
    if (r < 0) {
288
0
      sc_log(card->ctx,  " Failed to add cert obj r=%d",r);
289
0
      sc_pkcs15_free_certificate(cert_out);
290
0
      free(cert_info.value.value);
291
0
      continue;
292
0
    }
293
    /* set the token name to the name of the CN of the first certificate */
294
361
    if (!token_name) {
295
302
      u8 * cn_name = NULL;
296
302
      size_t cn_len = 0;
297
302
      static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }};
298
302
      r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject,
299
302
        cert_out->subject_len, &cn_oid, &cn_name, &cn_len);
300
302
      if (r == SC_SUCCESS) {
301
70
        token_name = malloc (cn_len+1);
302
70
        if (!token_name) {
303
0
          free(cn_name);
304
0
          r = SC_ERROR_OUT_OF_MEMORY;
305
0
          goto fail;
306
0
        }
307
70
        memcpy(token_name, cn_name, cn_len);
308
70
        free(cn_name);
309
70
        token_name[cn_len] = 0;
310
70
        free(p15card->tokeninfo->label);
311
70
        p15card->tokeninfo->label = token_name;
312
70
      }
313
302
    }
314
315
316
361
    r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len);
317
361
    if (r < 0)
318
0
      goto fail;
319
361
    pubkey_obj.emulated = cert_out->key;
320
321
361
    r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL);
322
361
    if (r < 0) {
323
266
      usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */
324
266
    }
325
361
    sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1);
326
361
    sc_log(card->ctx,   "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n",
327
361
        sc_dump_hex(cert_info.id.value, cert_info.id.len),
328
361
         usage, pubkey_info.usage, prkey_info.usage);
329
361
    if (cert_out->key->algorithm != SC_ALGORITHM_RSA) {
330
0
      sc_log(card->ctx, "unsupported key.algorithm %lu", cert_out->key->algorithm);
331
0
      sc_pkcs15_free_certificate(cert_out);
332
0
      free(pubkey_info.direct.spki.value);
333
0
      continue;
334
361
    } else {
335
361
      pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8;
336
361
      prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8;
337
361
      r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
338
361
      sc_log(card->ctx,  "adding rsa public key r=%d usage=%x",r, pubkey_info.usage);
339
361
      if (r < 0) {
340
0
        free(pubkey_info.direct.spki.value);
341
0
        goto fail;
342
0
      }
343
361
      pubkey_info.direct.spki.value = NULL; /* moved to the pubkey object on p15card  */
344
361
      pubkey_info.direct.spki.len = 0;
345
361
      r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
346
361
      if (r < 0)
347
0
        goto fail;
348
361
      sc_log(card->ctx,  "adding rsa private key r=%d usage=%x",r, prkey_info.usage);
349
361
    }
350
351
361
    cert_out->key = NULL;
352
361
fail:
353
361
    sc_pkcs15_free_certificate(cert_out);
354
361
    if (r < 0) {
355
0
      (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS, &count);
356
0
      LOG_TEST_GOTO_ERR(card->ctx, r, "Failed to add object.");
357
0
    }
358
359
361
  }
360
4.19k
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS, &count);
361
4.19k
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not finalize cert objects.");
362
363
4.19k
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
364
365
0
err:
366
0
  sc_pkcs15_card_clear(p15card);
367
0
  LOG_FUNC_RETURN(card->ctx, r);
368
0
}
369
370
int sc_pkcs15emu_cac_init_ex(sc_pkcs15_card_t *p15card,
371
    struct sc_aid *aid)
372
56.2k
{
373
56.2k
  sc_card_t   *card = p15card->card;
374
56.2k
  sc_context_t    *ctx = card->ctx;
375
376
56.2k
  LOG_FUNC_CALLED(ctx);
377
378
56.2k
  if (cac_detect_card(p15card))
379
52.0k
    return SC_ERROR_WRONG_CARD;
380
4.19k
  return sc_pkcs15emu_cac_init(p15card);
381
56.2k
}