Coverage Report

Created: 2025-07-01 06:08

/src/opensc/src/libopensc/card-cac1.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * card-cac1.c: Support for legacy CAC-1
3
 * card-default.c: Support for cards with no driver
4
 *
5
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
6
 * Copyright (C) 2005,2006,2007,2008,2009,2010 Douglas E. Engert <deengert@anl.gov>
7
 * Copyright (C) 2006, Identity Alliance, Thomas Harning <thomas.harning@identityalliance.com>
8
 * Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
9
 * Copyright (C) 2016 - 2018, Red Hat, Inc.
10
 *
11
 * CAC driver author: Robert Relyea <rrelyea@redhat.com>
12
 * Further work: Jakub Jelen <jjelen@redhat.com>
13
 *
14
 * This library is free software; you can redistribute it and/or
15
 * modify it under the terms of the GNU Lesser General Public
16
 * License as published by the Free Software Foundation; either
17
 * version 2.1 of the License, or (at your option) any later version.
18
 *
19
 * This library is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22
 * Lesser General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public
25
 * License along with this library; if not, write to the Free Software
26
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27
 */
28
29
#ifdef HAVE_CONFIG_H
30
#include "config.h"
31
#endif
32
33
#include <ctype.h>
34
#include <fcntl.h>
35
#include <limits.h>
36
#include <stdlib.h>
37
#include <string.h>
38
39
#ifdef _WIN32
40
#include <io.h>
41
#else
42
#include <unistd.h>
43
#endif
44
45
#ifdef ENABLE_OPENSSL
46
#include <openssl/sha.h>
47
#endif /* ENABLE_OPENSSL */
48
49
#include "internal.h"
50
#include "simpletlv.h"
51
#include "cardctl.h"
52
#include "iso7816.h"
53
#include "card-cac-common.h"
54
#include "pkcs15.h"
55
56
/*
57
 *  CAC hardware and APDU constants
58
 */
59
0
#define CAC_INS_GET_CERTIFICATE       0x36  /* CAC1 command to read a certificate */
60
61
/*
62
 * OLD cac read certificate, only use with CAC-1 card.
63
 */
64
static int cac_cac1_get_certificate(sc_card_t *card, u8 **out_buf, size_t *out_len)
65
0
{
66
0
  u8 buf[CAC_MAX_SIZE];
67
0
  u8 *out_ptr;
68
0
  size_t size = 0;
69
0
  size_t left = 0;
70
0
  size_t len;
71
0
  sc_apdu_t apdu;
72
0
  int r = SC_SUCCESS;
73
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
74
  /* get the size */
75
0
  size = left = *out_buf ? *out_len : sizeof(buf);
76
0
  out_ptr = *out_buf ? *out_buf : buf;
77
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, CAC_INS_GET_CERTIFICATE, 0, 0 );
78
0
  len = MIN(left, 100);
79
0
  while (left > 0) {
80
0
    apdu.resp = out_ptr;
81
0
    apdu.le = len;
82
0
    apdu.resplen = left;
83
0
    r = sc_transmit_apdu(card, &apdu);
84
0
    if (r < 0) {
85
0
      break;
86
0
    }
87
0
    if (apdu.resplen == 0) {
88
0
      r = SC_ERROR_INTERNAL;
89
0
      break;
90
0
    }
91
    /* in the old CAC-1, 0x63 means 'more data' in addition to 'pin failed' */
92
0
    if (apdu.sw1 != 0x63 || apdu.sw2 < 1)  {
93
      /* we've either finished reading, or hit an error, break */
94
0
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
95
0
      left -= apdu.resplen;
96
0
      break;
97
0
    }
98
    /* Adjust the lengths */
99
0
    left -= apdu.resplen;
100
0
    out_ptr += apdu.resplen;
101
0
    len = MIN(left, apdu.sw2);
102
0
  }
103
0
  if (r < 0) {
104
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
105
0
  }
106
0
  r = (int)(size - left);
107
0
  if (*out_buf == NULL) {
108
0
    *out_buf = malloc(r);
109
0
    if (*out_buf == NULL) {
110
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,
111
0
        SC_ERROR_OUT_OF_MEMORY);
112
0
    }
113
0
    memcpy(*out_buf, buf, r);
114
0
  }
115
0
  *out_len = r;
116
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
117
0
}
118
119
/*
120
 * Callers of this may be expecting a certificate,
121
 * select file will have saved the object type for us
122
 * as well as set that we want the cert from the object.
123
 */
124
static int cac_read_binary(sc_card_t *card, unsigned int idx,
125
    unsigned char *buf, size_t count, unsigned long *flags)
126
0
{
127
0
  cac_private_data_t * priv = CAC_DATA(card);
128
0
  int r = 0;
129
0
  u8 *val = NULL;
130
0
  u8 *cert_ptr;
131
0
  size_t val_len = 0;
132
0
  size_t len, cert_len;
133
0
  u8 cert_type;
134
135
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
136
137
  /* if we didn't return it all last time, return the remainder */
138
0
  if (priv->cached) {
139
0
    sc_log(card->ctx,
140
0
      "returning cached value idx=%d count=%"SC_FORMAT_LEN_SIZE_T"u",
141
0
      idx, count);
142
0
    if (idx > priv->cache_buf_len) {
143
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_END_REACHED);
144
0
    }
145
0
    len = MIN(count, priv->cache_buf_len-idx);
146
0
    memcpy(buf, &priv->cache_buf[idx], len);
147
0
    LOG_FUNC_RETURN(card->ctx, (int)len);
148
0
  }
149
150
0
  sc_log(card->ctx,
151
0
    "clearing cache idx=%d count=%"SC_FORMAT_LEN_SIZE_T"u",
152
0
    idx, count);
153
0
  free(priv->cache_buf);
154
0
  priv->cache_buf = NULL;
155
0
  priv->cache_buf_len = 0;
156
157
0
  r = cac_cac1_get_certificate(card, &val, &val_len);
158
0
  if (r < 0)
159
0
    goto done;
160
0
  if (val_len < 1) {
161
0
    r = SC_ERROR_INVALID_DATA;
162
0
    goto done;
163
0
  }
164
165
0
  cert_type = val[0];
166
0
  cert_ptr = val + 1;
167
0
  cert_len = val_len - 1;
168
169
  /* if the info byte is 1, then the cert is compressed, decompress it */
170
0
  if ((cert_type & 0x3) == 1) {
171
0
    *flags |= SC_FILE_FLAG_COMPRESSED_AUTO;
172
0
  }
173
0
  if (cert_len > 0) {
174
0
    priv->cache_buf = malloc(cert_len);
175
0
    if (priv->cache_buf == NULL) {
176
0
      r = SC_ERROR_OUT_OF_MEMORY;
177
0
      goto done;
178
0
    }
179
0
    priv->cache_buf_len = cert_len;
180
0
    memcpy(priv->cache_buf, cert_ptr, cert_len);
181
0
  }
182
183
  /* OK we've read the data, now copy the required portion out to the callers buffer */
184
0
  priv->cached = 1;
185
0
  len = MIN(count, priv->cache_buf_len-idx);
186
0
  if (len && priv->cache_buf)
187
0
    memcpy(buf, &priv->cache_buf[idx], len);
188
0
  r = (int)len;
189
0
done:
190
0
  if (val)
191
0
    free(val);
192
0
  LOG_FUNC_RETURN(card->ctx, r);
193
0
}
194
195
/*
196
 * CAC cards use SC_PATH_SELECT_OBJECT_ID rather than SC_PATH_SELECT_FILE_ID. In order to use more
197
 * of the PKCS #15 structure, we call the selection SC_PATH_SELECT_FILE_ID, but we set p1 to 2 instead
198
 * of 0. Also cac1 does not do any FCI, but it doesn't understand not selecting it. It returns invalid INS
199
 * if it doesn't like anything about the select, so we always 'request' FCI for CAC1
200
 *
201
 * The rest is just copied from iso7816_select_file
202
 */
203
static int cac_select_file_by_type(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
204
0
{
205
0
  struct sc_context *ctx;
206
0
  struct sc_apdu apdu;
207
0
  unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
208
0
  unsigned char pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
209
0
  int r, pathtype;
210
0
  size_t pathlen;
211
0
  struct sc_file *file = NULL;
212
0
  cac_private_data_t * priv = CAC_DATA(card);
213
214
0
  assert(card != NULL && in_path != NULL);
215
0
  ctx = card->ctx;
216
217
0
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
218
219
0
  memcpy(path, in_path->value, in_path->len);
220
0
  pathlen = in_path->len;
221
0
  pathtype = in_path->type;
222
223
0
  sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
224
0
    "path=%s, path->value=%s path->type=%d (%x)",
225
0
    sc_print_path(in_path),
226
0
    sc_dump_hex(in_path->value, in_path->len),
227
0
    in_path->type, in_path->type);
228
0
  sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "file_out=%p index=%d count=%d\n",
229
0
    file_out, in_path->index, in_path->count);
230
231
  /* Sigh, iso7816_select_file expects paths to keys to have specific
232
   * formats. There is no override. We have to add some bytes to the
233
   * path to make it happy.
234
   * We only need to do this for private keys.
235
   */
236
0
  if ((pathlen > 2) && (pathlen <= 4) && memcmp(path, "\x3F\x00", 2) == 0) {
237
0
    path += 2;
238
0
    pathlen -= 2;
239
0
  }
240
241
242
  /* CAC has multiple different type of objects that aren't PKCS #15. When we read
243
   * them we need convert them to something PKCS #15 would understand. Find the object
244
   * and object type here:
245
   */
246
0
  if (priv) { /* don't record anything if we haven't been initialized yet */
247
    /* forget any old cached values */
248
0
    if (priv->cache_buf) {
249
0
      free(priv->cache_buf);
250
0
      priv->cache_buf = NULL;
251
0
    }
252
0
    priv->cache_buf_len = 0;
253
0
    priv->cached = 0;
254
0
  }
255
256
0
  if (in_path->aid.len) {
257
0
    if (!pathlen) {
258
0
      memcpy(path, in_path->aid.value, in_path->aid.len);
259
0
      pathlen = in_path->aid.len;
260
0
      pathtype = SC_PATH_TYPE_DF_NAME;
261
0
    } else {
262
      /* First, select the application */
263
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"select application" );
264
0
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 4, 0);
265
0
      apdu.data = in_path->aid.value;
266
0
      apdu.datalen = in_path->aid.len;
267
0
      apdu.lc = in_path->aid.len;
268
269
0
      r = sc_transmit_apdu(card, &apdu);
270
0
      LOG_TEST_RET(ctx, r, "APDU transmit failed");
271
0
      r = sc_check_sw(card, apdu.sw1, apdu.sw2);
272
0
      if (r)
273
0
        LOG_FUNC_RETURN(ctx, r);
274
275
0
    }
276
0
  }
277
278
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
279
280
0
  switch (pathtype) {
281
  /* ideally we would had SC_PATH_TYPE_OBJECT_ID and add code to the iso7816 select.
282
   * Unfortunately we'd also need to update the caching code as well. For now just
283
   * use FILE_ID and change p1 here */
284
0
  case SC_PATH_TYPE_FILE_ID:
285
0
    apdu.p1 = 2;
286
0
    if (pathlen != 2)
287
0
      return SC_ERROR_INVALID_ARGUMENTS;
288
0
    break;
289
0
  case SC_PATH_TYPE_DF_NAME:
290
0
    apdu.p1 = 4;
291
0
    break;
292
0
  default:
293
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
294
0
  }
295
0
  apdu.lc = pathlen;
296
0
  apdu.data = path;
297
0
  apdu.datalen = pathlen;
298
0
  apdu.resp = buf;
299
0
  apdu.resplen = sizeof(buf);
300
0
  apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256;
301
0
  apdu.p2 = 0x00;
302
303
0
  r = sc_transmit_apdu(card, &apdu);
304
0
  LOG_TEST_RET(ctx, r, "APDU transmit failed");
305
306
0
  if (file_out == NULL) {
307
    /* For some cards 'SELECT' can be only with request to return FCI/FCP. */
308
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
309
0
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x86)   {
310
0
      apdu.p2 = 0x00;
311
0
      apdu.resplen = sizeof(buf);
312
0
      if (sc_transmit_apdu(card, &apdu) == SC_SUCCESS)
313
0
        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
314
0
    }
315
0
    if (apdu.sw1 == 0x61)
316
0
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
317
0
    LOG_FUNC_RETURN(ctx, r);
318
0
  }
319
320
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
321
0
  if (r)
322
0
    LOG_FUNC_RETURN(ctx, r);
323
324
  /* CAC cards never return FCI, fake one */
325
0
  file = sc_file_new();
326
0
  if (file == NULL)
327
0
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
328
0
  file->path = *in_path;
329
0
  file->size = CAC_MAX_SIZE; /* we don't know how big, just give a large size until we can read the file */
330
331
0
  *file_out = file;
332
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
333
334
0
}
335
336
static int cac_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
337
0
{
338
0
  return cac_select_file_by_type(card, in_path, file_out);
339
0
}
340
341
static int cac_finish(sc_card_t *card)
342
0
{
343
0
  cac_private_data_t * priv = CAC_DATA(card);
344
345
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
346
0
  if (priv) {
347
0
    cac_free_private_data(priv);
348
0
  }
349
0
  return SC_SUCCESS;
350
0
}
351
352
353
/* select a CAC pki applet by index */
354
static int cac_select_pki_applet(sc_card_t *card, int index)
355
0
{
356
0
  sc_path_t applet_path = cac_cac_pki_obj.path;
357
0
  applet_path.aid.value[applet_path.aid.len-1] = index;
358
0
  return cac_select_file_by_type(card, &applet_path, NULL);
359
0
}
360
361
/*
362
 *  Find the first existing CAC applet. If none found, then this isn't a CAC
363
 */
364
static int cac_find_first_pki_applet(sc_card_t *card, int *index_out)
365
0
{
366
0
  int r, i;
367
368
0
  for (i = 0; i < MAX_CAC_SLOTS; i++) {
369
0
    r = cac_select_pki_applet(card, i);
370
0
    if (r == SC_SUCCESS) {
371
0
      u8 data[2];
372
0
      sc_apdu_t apdu;
373
374
      /* Try to read first two bytes of the buffer to
375
       * make sure it is not just malfunctioning card
376
       */
377
0
      sc_format_apdu(card, &apdu, SC_APDU_CASE_2,
378
0
        CAC_INS_GET_CERTIFICATE, 0x00, 0x00);
379
0
      apdu.le = 0x02;
380
0
      apdu.resplen = 2;
381
0
      apdu.resp = data;
382
0
      r = sc_transmit_apdu(card, &apdu);
383
      /* SW1 = 0x63 means more data in CAC1 */
384
0
      if (r == SC_SUCCESS && apdu.sw1 != 0x63)
385
0
        continue;
386
387
0
      *index_out = i;
388
0
      return SC_SUCCESS;
389
0
    }
390
0
  }
391
0
  return SC_ERROR_OBJECT_NOT_FOUND;
392
0
}
393
394
static int cac_populate_cac1(sc_card_t *card, int index, cac_private_data_t *priv)
395
0
{
396
0
  int r, i;
397
0
  cac_object_t pki_obj = cac_cac_pki_obj;
398
0
  u8 buf[100];
399
0
  u8 *val;
400
0
  size_t val_len;
401
402
  /* populate PKI objects */
403
0
  for (i = index; i < MAX_CAC_SLOTS; i++) {
404
0
    r = cac_select_pki_applet(card, i);
405
0
    if (r == SC_SUCCESS) {
406
0
      pki_obj.name = get_cac_label(i);
407
0
      sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,
408
0
        "CAC: pki_object found, cert_next=%d (%s)",
409
0
        i, pki_obj.name);
410
0
      pki_obj.path.aid.value[pki_obj.path.aid.len-1] = i;
411
0
      pki_obj.fd = i+1; /* don't use id of zero */
412
0
      cac_add_object_to_list(&priv->pki_list, &pki_obj);
413
0
    }
414
0
  }
415
416
  /*
417
   * create a cuid to simulate the cac 2 cuid.
418
   */
419
0
  priv->cuid = cac_cac_cuid;
420
  /* create a serial number by hashing the first 100 bytes of the
421
   * first certificate on the card */
422
0
  r = cac_select_pki_applet(card, index);
423
0
  if (r < 0) {
424
0
    return r; /* shouldn't happen unless the card has been removed or is malfunctioning */
425
0
  }
426
0
  val = buf;
427
0
  val_len = sizeof(buf);
428
0
  r = cac_cac1_get_certificate(card, &val, &val_len);
429
0
  if (r >= 0) {
430
0
    priv->cac_id = malloc(20);
431
0
    if (priv->cac_id == NULL) {
432
0
      return SC_ERROR_OUT_OF_MEMORY;
433
0
    }
434
0
#ifdef ENABLE_OPENSSL
435
0
    SHA1(val, val_len, priv->cac_id);
436
0
    priv->cac_id_len = 20;
437
0
    sc_debug_hex(card->ctx, SC_LOG_DEBUG_VERBOSE,
438
0
      "cuid", priv->cac_id, priv->cac_id_len);
439
#else
440
    sc_log(card->ctx, "OpenSSL Required");
441
    return SC_ERROR_NOT_SUPPORTED;
442
#endif /* ENABLE_OPENSSL */
443
0
  }
444
0
  return SC_SUCCESS;
445
0
}
446
447
/*
448
 * Look for a CAC card. If it exists, initialize our data structures
449
 */
450
static int cac_find_and_initialize(sc_card_t *card, int initialize)
451
0
{
452
0
  int r, index;
453
0
  cac_private_data_t *priv = NULL;
454
455
  /* already initialized? */
456
0
  if (card->drv_data) {
457
0
    return SC_SUCCESS;
458
0
  }
459
460
  /* is this a CAC Alt token without any accompanying structures */
461
0
  r = cac_find_first_pki_applet(card, &index);
462
0
  if (r == SC_SUCCESS) {
463
0
    sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "PKI applet found, is bare CAC-1");
464
0
    if (!initialize) /* match card only */
465
0
      return r;
466
467
0
    if (!priv) {
468
0
      priv = cac_new_private_data();
469
0
      if (!priv)
470
0
        return SC_ERROR_OUT_OF_MEMORY;
471
0
    }
472
0
    card->drv_data = priv; /* needed for the read_binary() */
473
0
    r = cac_populate_cac1(card, index, priv);
474
0
    if (r == SC_SUCCESS) {
475
0
      card->type = SC_CARD_TYPE_CAC_I;
476
0
      return r;
477
0
    }
478
0
    card->drv_data = NULL; /* reset on failure */
479
0
  }
480
0
  if (priv) {
481
0
    cac_free_private_data(priv);
482
0
  }
483
0
  return r;
484
0
}
485
486
487
/* NOTE: returns a bool, 1 card matches, 0 it does not */
488
static int cac_match_card(sc_card_t *card)
489
0
{
490
0
  int r;
491
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
492
493
0
  r = cac_find_and_initialize(card, 0);
494
0
  return (r == SC_SUCCESS); /* never match */
495
0
}
496
497
498
static int cac_init(sc_card_t *card)
499
0
{
500
0
  int r;
501
0
  unsigned long flags;
502
503
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
504
505
0
  r = cac_find_and_initialize(card, 1);
506
0
  if (r < 0) {
507
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD);
508
0
  }
509
0
  flags = SC_ALGORITHM_RSA_RAW;
510
511
0
  _sc_card_add_rsa_alg(card, 1024, flags, 0); /* mandatory */
512
0
  _sc_card_add_rsa_alg(card, 2048, flags, 0); /* optional */
513
0
  _sc_card_add_rsa_alg(card, 3072, flags, 0); /* optional */
514
515
0
  card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO;
516
517
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
518
0
}
519
520
static int cac_logout(sc_card_t *card)
521
0
{
522
0
  int index;
523
0
  return cac_find_first_pki_applet(card, &index);
524
0
}
525
526
static struct sc_card_operations cac_ops;
527
528
static struct sc_card_driver cac1_drv = {
529
  "Common Access Card (CAC 1)",
530
  "cac1",
531
  &cac_ops,
532
  NULL, 0, NULL
533
};
534
535
static struct sc_card_driver * sc_get_driver(void)
536
0
{
537
  /* Inherit most of the things from the CAC driver */
538
0
  struct sc_card_driver *cac_drv = sc_get_cac_driver();
539
540
0
  cac_ops = *cac_drv->ops;
541
0
  cac_ops.match_card = cac_match_card;
542
0
  cac_ops.init = cac_init;
543
0
  cac_ops.finish = cac_finish;
544
545
0
  cac_ops.select_file =  cac_select_file; /* need to record object type */
546
0
  cac_ops.read_binary = cac_read_binary;
547
0
  cac_ops.logout = cac_logout;
548
549
0
  return &cac1_drv;
550
0
}
551
552
553
struct sc_card_driver * sc_get_cac1_driver(void)
554
0
{
555
0
  return sc_get_driver();
556
0
}