Coverage Report

Created: 2025-11-24 06:43

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
849
#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
10.2k
{
66
10.2k
  sc_card_t *card = p15card->card;
67
68
10.2k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
69
10.2k
  if (card->type < SC_CARD_TYPE_CAC_GENERIC
70
1.43k
    || card->type >= SC_CARD_TYPE_CAC_GENERIC+1000)
71
9.37k
    return SC_ERROR_INVALID_CARD;
72
849
  return SC_SUCCESS;
73
10.2k
}
74
75
#define CAC_NUM_CERTS_AND_KEYS 10
76
77
static const char * cac_get_name(int type)
78
849
{
79
849
    switch (type) {
80
128
    case SC_CARD_TYPE_CAC_I: return ("CAC I");
81
396
    case SC_CARD_TYPE_CAC_II: return ("CAC II");
82
325
    case SC_CARD_TYPE_CAC_ALT_HID: return ("CAC ALT HID");
83
0
    default: break;
84
849
    }
85
0
    return ("CAC");
86
849
}
87
88
static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card)
89
849
{
90
849
  static const pindata pins[] = {
91
849
    { "1", "PIN", "", 0x00,
92
849
      SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
93
849
      8, 4, 8,
94
849
      SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
95
849
      SC_PKCS15_PIN_FLAG_INITIALIZED ,
96
849
      -1, 0xFF,
97
849
      SC_PKCS15_CO_FLAG_PRIVATE },
98
849
    { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
99
849
  };
100
  /* oid for key usage */
101
849
  static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }};
102
849
  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
849
  int    r, i;
113
849
  sc_card_t *card = p15card->card;
114
849
  sc_serial_number_t serial;
115
849
  char buf[SC_MAX_SERIALNR * 2 + 1];
116
849
  int count;
117
849
  char *token_name = NULL;
118
119
120
849
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
121
122
849
  memset(&serial, 0, sizeof(serial));
123
124
  /* could read this off card if needed */
125
126
849
  set_string(&p15card->tokeninfo->label, cac_get_name(card->type));
127
849
  set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID);
128
129
  /*
130
   * get serial number
131
   */
132
849
  r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
133
849
  if (r < 0) {
134
676
    sc_log(card->ctx, "sc_card_ctl rc=%d",r);
135
676
    set_string(&p15card->tokeninfo->serial_number, "00000000");
136
676
  } else {
137
173
    sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
138
173
    set_string(&p15card->tokeninfo->serial_number, buf);
139
173
  }
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
849
  sc_log(card->ctx,  "CAC adding pins...");
146
1.69k
  for (i = 0; pins[i].id; i++) {
147
849
    struct sc_pkcs15_auth_info pin_info;
148
849
    struct sc_pkcs15_object   pin_obj;
149
849
    const char * label;
150
151
849
    memset(&pin_info, 0, sizeof(pin_info));
152
849
    memset(&pin_obj,  0, sizeof(pin_obj));
153
154
849
    pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
155
849
    sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
156
849
    pin_info.attrs.pin.reference     = pins[i].ref;
157
849
    pin_info.attrs.pin.flags         = pins[i].flags;
158
849
    pin_info.attrs.pin.type          = pins[i].type;
159
849
    pin_info.attrs.pin.min_length    = pins[i].minlen;
160
849
    pin_info.attrs.pin.stored_length = pins[i].storedlen;
161
849
    pin_info.attrs.pin.max_length    = pins[i].maxlen;
162
849
    pin_info.attrs.pin.pad_char      = pins[i].pad_char;
163
849
    sc_format_path(pins[i].path, &pin_info.path);
164
849
    pin_info.tries_left    = -1;
165
166
849
    label = pins[i].label;
167
849
    sc_log(card->ctx,  "CAC Adding pin %d label=%s",i, label);
168
849
    strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1);
169
849
    pin_obj.flags = pins[i].obj_flags;
170
171
    /* get the ACA path in case it needs to be selected before PIN verify */
172
849
    r = sc_card_ctl(card, SC_CARDCTL_CAC_GET_ACA_PATH, &pin_info.path);
173
849
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not get ACA path.");
174
175
849
    r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
176
849
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not add pin object.");
177
849
  }
178
179
  /* set other objects */
180
849
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_GENERIC_OBJECTS, &count);
181
849
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not initiate generic objects.");
182
183
4.02k
  for (i = 0; i < count; i++) {
184
3.18k
    struct sc_pkcs15_data_info obj_info;
185
3.18k
    struct sc_pkcs15_object    obj_obj;
186
187
3.18k
    r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_GENERIC_OBJECT, &obj_info);
188
3.18k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not get next generic object.");
189
3.18k
    memset(&obj_obj, 0, sizeof(obj_obj));
190
3.18k
    memcpy(obj_obj.label, obj_info.app_label, sizeof(obj_obj.label));
191
192
3.18k
    r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
193
3.18k
      &obj_obj, &obj_info);
194
3.18k
    LOG_TEST_GOTO_ERR(card->ctx, r, "Can not finalize generic object.");
195
3.18k
  }
196
849
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS, &count);
197
849
  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
849
  sc_log(card->ctx,  "CAC adding certs, pub and priv keys...");
206
849
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_CERT_OBJECTS, &count);
207
849
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not initiate cert objects.");
208
209
3.86k
  for (i = 0; i < count; i++) {
210
3.01k
    struct sc_pkcs15_data_info obj_info;
211
3.01k
    struct sc_pkcs15_cert_info cert_info;
212
3.01k
    struct sc_pkcs15_pubkey_info pubkey_info;
213
3.01k
    struct sc_pkcs15_prkey_info prkey_info;
214
3.01k
    struct sc_pkcs15_object cert_obj;
215
3.01k
    struct sc_pkcs15_object pubkey_obj;
216
3.01k
    struct sc_pkcs15_object prkey_obj;
217
3.01k
    sc_pkcs15_der_t   cert_der;
218
3.01k
    sc_pkcs15_cert_t *cert_out = NULL;
219
220
3.01k
    r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT, &obj_info);
221
3.01k
    LOG_TEST_RET(card->ctx, r, "Can not get next object");
222
223
3.01k
    memset(&cert_info, 0, sizeof(cert_info));
224
3.01k
    memset(&pubkey_info, 0, sizeof(pubkey_info));
225
3.01k
    memset(&prkey_info, 0, sizeof(prkey_info));
226
3.01k
    memset(&cert_obj,  0, sizeof(cert_obj));
227
3.01k
    memset(&pubkey_obj,  0, sizeof(pubkey_obj));
228
3.01k
    memset(&prkey_obj,  0, sizeof(prkey_obj));
229
230
3.01k
    cert_info.id = obj_info.id;
231
3.01k
    pubkey_info.id = obj_info.id;
232
3.01k
    prkey_info.id = obj_info.id;
233
3.01k
    cert_info.path = obj_info.path;
234
3.01k
    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
3.01k
    if (prkey_info.path.len && prkey_info.path.len <= 2) {
238
1.18k
      prkey_info.path.value[2] = prkey_info.path.value[0];
239
1.18k
      prkey_info.path.value[3] = prkey_info.path.value[1];
240
1.18k
      prkey_info.path.value[0] = 0x3f;
241
1.18k
      prkey_info.path.value[1] = 0x00;
242
1.18k
      prkey_info.path.len += 2;
243
1.18k
    }
244
3.01k
    pubkey_info.native        = 1;
245
3.01k
    pubkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1];
246
3.01k
    prkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1];
247
3.01k
    prkey_info.native        = 1;
248
249
3.01k
    memcpy(cert_obj.label, obj_info.app_label, sizeof(obj_info.app_label));
250
3.01k
    memcpy(pubkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label));
251
3.01k
    memcpy(prkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label));
252
3.01k
    prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
253
3.01k
    sc_pkcs15_format_id(pins[0].id, &prkey_obj.auth_id);
254
255
3.01k
    r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, 0);
256
257
3.01k
    if (r) {
258
2.59k
      sc_log(card->ctx,  "No cert found,i=%d", i);
259
2.59k
      continue;
260
2.59k
    }
261
424
    cert_info.path.count = (int)cert_der.len;
262
263
424
    sc_log(card->ctx,
264
424
       "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n",
265
424
       cert_der.len, cert_info.path.count, r);
266
424
    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
424
    if (cert_der.value) {
271
306
      cert_info.value.value = cert_der.value;
272
306
      cert_info.value.len = cert_der.len;
273
306
      cert_info.path.len = 0; /* use in mem cert from now on */
274
306
    }
275
276
    /* following will find the cached cert in cert_info */
277
424
    r =  sc_pkcs15_read_certificate(p15card, &cert_info, 0, &cert_out);
278
424
    if (r < 0 || cert_out->key == NULL) {
279
267
      sc_log(card->ctx,  "Failed to read/parse the certificate r=%d",r);
280
267
      if (cert_out != NULL)
281
0
        sc_pkcs15_free_certificate(cert_out);
282
267
      free(cert_info.value.value);
283
267
      continue;
284
267
    }
285
286
157
    r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
287
157
    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
157
    if (!token_name) {
295
142
      u8 * cn_name = NULL;
296
142
      size_t cn_len = 0;
297
142
      static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }};
298
142
      r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject,
299
142
        cert_out->subject_len, &cn_oid, &cn_name, &cn_len);
300
142
      if (r == SC_SUCCESS) {
301
13
        token_name = malloc (cn_len+1);
302
13
        if (!token_name) {
303
0
          free(cn_name);
304
0
          r = SC_ERROR_OUT_OF_MEMORY;
305
0
          goto fail;
306
0
        }
307
13
        memcpy(token_name, cn_name, cn_len);
308
13
        free(cn_name);
309
13
        token_name[cn_len] = 0;
310
13
        free(p15card->tokeninfo->label);
311
13
        p15card->tokeninfo->label = token_name;
312
13
      }
313
142
    }
314
315
316
157
    r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len);
317
157
    if (r < 0)
318
0
      goto fail;
319
157
    pubkey_obj.emulated = cert_out->key;
320
321
157
    r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL);
322
157
    if (r < 0) {
323
130
      usage = SC_X509_DATA_ENCIPHERMENT|SC_X509_DIGITAL_SIGNATURE; /* basic default usage */
324
130
    }
325
157
    sc_pkcs15_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1);
326
157
    sc_log(card->ctx,   "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n",
327
157
        sc_dump_hex(cert_info.id.value, cert_info.id.len),
328
157
         usage, pubkey_info.usage, prkey_info.usage);
329
157
    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
157
    } else {
335
157
      pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8;
336
157
      prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8;
337
157
      r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
338
157
      sc_log(card->ctx,  "adding rsa public key r=%d usage=%x",r, pubkey_info.usage);
339
157
      if (r < 0) {
340
0
        free(pubkey_info.direct.spki.value);
341
0
        goto fail;
342
0
      }
343
157
      pubkey_info.direct.spki.value = NULL; /* moved to the pubkey object on p15card  */
344
157
      pubkey_info.direct.spki.len = 0;
345
157
      r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
346
157
      if (r < 0)
347
0
        goto fail;
348
157
      sc_log(card->ctx,  "adding rsa private key r=%d usage=%x",r, prkey_info.usage);
349
157
    }
350
351
157
    cert_out->key = NULL;
352
157
fail:
353
157
    sc_pkcs15_free_certificate(cert_out);
354
157
    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
157
  }
360
849
  r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS, &count);
361
849
  LOG_TEST_GOTO_ERR(card->ctx, r, "Can not finalize cert objects.");
362
363
849
  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
10.2k
{
373
10.2k
  sc_card_t   *card = p15card->card;
374
10.2k
  sc_context_t    *ctx = card->ctx;
375
376
10.2k
  LOG_FUNC_CALLED(ctx);
377
378
10.2k
  if (cac_detect_card(p15card))
379
9.37k
    return SC_ERROR_WRONG_CARD;
380
849
  return sc_pkcs15emu_cac_init(p15card);
381
10.2k
}