Coverage Report

Created: 2025-07-01 06:08

/src/opensc/src/libopensc/sc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * sc.c: General functions
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
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 <stdio.h>
26
#include <ctype.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <assert.h>
30
#ifdef HAVE_SYS_MMAN_H
31
#include <sys/mman.h>
32
#endif
33
#ifdef ENABLE_OPENSSL
34
#include <openssl/crypto.h>     /* for OPENSSL_cleanse */
35
#endif
36
37
38
#include "internal.h"
39
40
#ifdef PACKAGE_VERSION
41
static const char *sc_version = PACKAGE_VERSION;
42
#else
43
static const char *sc_version = "(undef)";
44
#endif
45
46
#ifdef _WIN32
47
#include <windows.h>
48
#define PAGESIZE 0
49
#else
50
#include <sys/mman.h>
51
#include <limits.h>
52
#include <unistd.h>
53
#ifndef PAGESIZE
54
#define PAGESIZE 0
55
#endif
56
#endif
57
58
const char *sc_get_version(void)
59
0
{
60
0
    return sc_version;
61
0
}
62
63
int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen)
64
0
{
65
0
  const char *sc_hex_to_bin_separators = " :";
66
0
  if (in == NULL || out == NULL || outlen == NULL) {
67
0
    return SC_ERROR_INVALID_ARGUMENTS;
68
0
  }
69
70
0
  int byte_needs_nibble = 0;
71
0
  int r = SC_SUCCESS;
72
0
  size_t left = *outlen;
73
0
  u8 byte = 0;
74
0
  while (*in != '\0' && 0 != left) {
75
0
    char c = *in++;
76
0
    u8 nibble;
77
0
    if      ('0' <= c && c <= '9')
78
0
      nibble = c - '0';
79
0
    else if ('a' <= c && c <= 'f')
80
0
      nibble = c - 'a' + 10;
81
0
    else if ('A' <= c && c <= 'F')
82
0
      nibble = c - 'A' + 10;
83
0
    else {
84
0
      if (strchr(sc_hex_to_bin_separators, (int) c)) {
85
0
        if (byte_needs_nibble) {
86
0
          r = SC_ERROR_INVALID_ARGUMENTS;
87
0
          goto err;
88
0
        }
89
0
        continue;
90
0
      }
91
0
      r = SC_ERROR_INVALID_ARGUMENTS;
92
0
      goto err;
93
0
    }
94
95
0
    if (byte_needs_nibble) {
96
0
      byte |= nibble;
97
0
      *out++ = (u8) byte;
98
0
      left--;
99
0
      byte_needs_nibble = 0;
100
0
    } else {
101
0
      byte  = nibble << 4;
102
0
      byte_needs_nibble = 1;
103
0
    }
104
0
  }
105
106
0
  if (left == *outlen && 1 == byte_needs_nibble && 0 != left) {
107
    /* no output written so far, but we have a valid nibble in the upper
108
     * bits. Allow this special case. */
109
0
    *out = (u8) byte>>4;
110
0
    left--;
111
0
    byte_needs_nibble = 0;
112
0
  }
113
114
  /* for ease of implementation we only accept completely hexed bytes. */
115
0
  if (byte_needs_nibble) {
116
0
    r = SC_ERROR_INVALID_ARGUMENTS;
117
0
    goto err;
118
0
  }
119
120
  /* skip all trailing separators to see if we missed something */
121
0
  while (*in != '\0') {
122
0
    if (NULL == strchr(sc_hex_to_bin_separators, (int) *in))
123
0
      break;
124
0
    in++;
125
0
  }
126
0
  if (*in != '\0') {
127
0
    r = SC_ERROR_BUFFER_TOO_SMALL;
128
0
    goto err;
129
0
  }
130
131
0
err:
132
0
  *outlen -= left;
133
0
  return r;
134
0
}
135
136
int sc_bin_to_hex(const u8 *in, size_t in_len, char *out, size_t out_len,
137
          int in_sep)
138
0
{
139
0
  if (in == NULL || out == NULL) {
140
0
    return SC_ERROR_INVALID_ARGUMENTS;
141
0
  }
142
143
0
  if (in_sep > 0) {
144
0
    if (out_len < in_len*3 || out_len < 1)
145
0
      return SC_ERROR_BUFFER_TOO_SMALL;
146
0
  } else {
147
0
    if (out_len < in_len*2 + 1)
148
0
      return SC_ERROR_BUFFER_TOO_SMALL;
149
0
  }
150
151
0
  const char hex[] = "0123456789abcdef";
152
0
  while (in_len) {
153
0
    unsigned char value = *in++;
154
0
    *out++ = hex[(value >> 4) & 0xF];
155
0
    *out++ = hex[ value       & 0xF];
156
0
    in_len--;
157
0
    if (in_len && in_sep > 0)
158
0
      *out++ = (char)in_sep;
159
0
  }
160
0
  *out = '\0';
161
162
0
  return SC_SUCCESS;
163
0
}
164
165
/*
166
 * Right trim all non-printable characters
167
 */
168
0
size_t sc_right_trim(u8 *buf, size_t len) {
169
170
0
  size_t i;
171
172
0
  if (!buf)
173
0
    return 0;
174
175
0
  if (len > 0) {
176
0
    for(i = len-1; i > 0; i--) {
177
0
      if(!isprint(buf[i])) {
178
0
        buf[i] = '\0';
179
0
        len--;
180
0
        continue;
181
0
      }
182
0
      break;
183
0
    }
184
0
  }
185
0
  return len;
186
0
}
187
188
u8 *ulong2bebytes(u8 *buf, unsigned long x)
189
0
{
190
0
  if (buf != NULL) {
191
0
    buf[3] = (u8) (x & 0xff);
192
0
    buf[2] = (u8) ((x >> 8) & 0xff);
193
0
    buf[1] = (u8) ((x >> 16) & 0xff);
194
0
    buf[0] = (u8) ((x >> 24) & 0xff);
195
0
  }
196
0
  return buf;
197
0
}
198
199
u8 *ushort2bebytes(u8 *buf, unsigned short x)
200
0
{
201
0
  if (buf != NULL) {
202
0
    buf[1] = (u8) (x & 0xff);
203
0
    buf[0] = (u8) ((x >> 8) & 0xff);
204
0
  }
205
0
  return buf;
206
0
}
207
208
unsigned long bebytes2ulong(const u8 *buf)
209
0
{
210
0
  if (buf == NULL)
211
0
    return 0UL;
212
0
  return (unsigned long)buf[0] << 24
213
0
    | (unsigned long)buf[1] << 16
214
0
    | (unsigned long)buf[2] << 8
215
0
    | (unsigned long)buf[3];
216
0
}
217
218
unsigned short bebytes2ushort(const u8 *buf)
219
0
{
220
0
  if (buf == NULL)
221
0
    return 0U;
222
0
  return (unsigned short)buf[0] << 8
223
0
    | (unsigned short)buf[1];
224
0
}
225
226
unsigned short lebytes2ushort(const u8 *buf)
227
0
{
228
0
  if (buf == NULL)
229
0
    return 0U;
230
0
  return (unsigned short)buf[1] << 8
231
0
    | (unsigned short)buf[0];
232
0
}
233
234
unsigned long lebytes2ulong(const u8 *buf)
235
0
{
236
0
  if (buf == NULL)
237
0
    return 0UL;
238
0
  return (unsigned long)buf[3] << 24
239
0
    | (unsigned long)buf[2] << 16
240
0
    | (unsigned long)buf[1] << 8
241
0
    | (unsigned long)buf[0];
242
0
}
243
244
void set_string(char **strp, const char *value)
245
0
{
246
0
  if (strp == NULL) {
247
0
    return;
248
0
  }
249
250
0
  free(*strp);
251
0
  *strp = value ? strdup(value) : NULL;
252
0
}
253
254
void sc_init_oid(struct sc_object_id *oid)
255
0
{
256
0
  int ii;
257
258
0
  if (!oid)
259
0
    return;
260
0
  for (ii=0; ii<SC_MAX_OBJECT_ID_OCTETS; ii++)
261
0
    oid->value[ii] = -1;
262
0
}
263
264
int sc_format_oid(struct sc_object_id *oid, const char *in)
265
0
{
266
0
  int        ii, ret = SC_ERROR_INVALID_ARGUMENTS;
267
0
  const char *p;
268
0
  char       *q;
269
270
0
  if (oid == NULL || in == NULL)
271
0
    return SC_ERROR_INVALID_ARGUMENTS;
272
273
0
  sc_init_oid(oid);
274
275
0
  p = in;
276
0
  for (ii=0; ii < SC_MAX_OBJECT_ID_OCTETS; ii++)   {
277
0
    oid->value[ii] = (int)strtol(p, &q, 10);
278
0
    if (!*q)
279
0
      break;
280
281
0
    if (!(q[0] == '.' && isdigit((unsigned char)q[1])))
282
0
      goto out;
283
284
0
    p = q + 1;
285
0
  }
286
287
0
  if (!sc_valid_oid(oid))
288
0
    goto out;
289
290
0
  ret = SC_SUCCESS;
291
0
out:
292
0
  if (ret)
293
0
    sc_init_oid(oid);
294
295
0
  return ret;
296
0
}
297
298
int sc_compare_oid(const struct sc_object_id *oid1, const struct sc_object_id *oid2)
299
0
{
300
0
  int i;
301
302
0
  if (oid1 == NULL || oid2 == NULL) {
303
0
    return SC_ERROR_INVALID_ARGUMENTS;
304
0
  }
305
306
0
  for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++)   {
307
0
    if (oid1->value[i] != oid2->value[i])
308
0
      return 0;
309
0
    if (oid1->value[i] == -1)
310
0
      break;
311
0
  }
312
313
0
  return 1;
314
0
}
315
316
317
int sc_valid_oid(const struct sc_object_id *oid)
318
0
{
319
0
  int ii;
320
321
0
  if (!oid)
322
0
    return 0;
323
0
  if (oid->value[0] == -1 || oid->value[1] == -1)
324
0
    return 0;
325
0
  if (oid->value[0] > 2 || oid->value[1] > 39)
326
0
    return 0;
327
0
  for (ii=0;ii<SC_MAX_OBJECT_ID_OCTETS;ii++)
328
0
    if (oid->value[ii])
329
0
      break;
330
0
  if (ii==SC_MAX_OBJECT_ID_OCTETS)
331
0
    return 0;
332
0
  return 1;
333
0
}
334
335
336
int sc_detect_card_presence(sc_reader_t *reader)
337
0
{
338
0
  int r;
339
0
  LOG_FUNC_CALLED(reader->ctx);
340
0
  if (reader->ops->detect_card_presence == NULL)
341
0
    LOG_FUNC_RETURN(reader->ctx, SC_ERROR_NOT_SUPPORTED);
342
343
0
  r = reader->ops->detect_card_presence(reader);
344
345
  // Check that we get sane return value from backend
346
  // detect_card_presence should return 0 if no card is present.
347
0
  if (r && !(r & SC_READER_CARD_PRESENT))
348
0
    LOG_FUNC_RETURN(reader->ctx, SC_ERROR_INTERNAL);
349
350
0
  LOG_FUNC_RETURN(reader->ctx, r);
351
0
}
352
353
int sc_path_set(sc_path_t *path, int type, const u8 *id, size_t id_len,
354
  int idx, int count)
355
0
{
356
0
  if (path == NULL || id == NULL || id_len == 0 || id_len > SC_MAX_PATH_SIZE)
357
0
    return SC_ERROR_INVALID_ARGUMENTS;
358
359
0
  memset(path, 0, sizeof(*path));
360
0
  memcpy(path->value, id, id_len);
361
0
  path->len   = id_len;
362
0
  path->type  = type;
363
0
  path->index = idx;
364
0
  path->count = count;
365
366
0
  return SC_SUCCESS;
367
0
}
368
369
void sc_format_path(const char *str, sc_path_t *path)
370
0
{
371
0
  int type = SC_PATH_TYPE_PATH;
372
373
0
  if (path) {
374
0
    memset(path, 0, sizeof(*path));
375
0
    if (*str == 'i' || *str == 'I') {
376
0
      type = SC_PATH_TYPE_FILE_ID;
377
0
      str++;
378
0
    }
379
0
    path->len = sizeof(path->value);
380
0
    if (sc_hex_to_bin(str, path->value, &path->len) >= 0) {
381
0
      path->type = type;
382
0
    }
383
0
    path->count = -1;
384
0
  }
385
0
}
386
387
int sc_append_path(sc_path_t *dest, const sc_path_t *src)
388
0
{
389
0
  return sc_concatenate_path(dest, dest, src);
390
0
}
391
392
int sc_append_path_id(sc_path_t *dest, const u8 *id, size_t idlen)
393
0
{
394
0
  if (dest->len + idlen > SC_MAX_PATH_SIZE)
395
0
    return SC_ERROR_INVALID_ARGUMENTS;
396
0
  memcpy(dest->value + dest->len, id, idlen);
397
0
  dest->len += idlen;
398
0
  return SC_SUCCESS;
399
0
}
400
401
int sc_append_file_id(sc_path_t *dest, unsigned int fid)
402
0
{
403
0
  u8 id[2] = { fid >> 8, fid & 0xff };
404
405
0
  return sc_append_path_id(dest, id, 2);
406
0
}
407
408
int sc_concatenate_path(sc_path_t *d, const sc_path_t *p1, const sc_path_t *p2)
409
0
{
410
0
  sc_path_t tpath;
411
412
0
  if (d == NULL || p1 == NULL || p2 == NULL)
413
0
    return SC_ERROR_INVALID_ARGUMENTS;
414
415
0
  if (p1->type == SC_PATH_TYPE_DF_NAME || p2->type == SC_PATH_TYPE_DF_NAME)
416
    /* we do not support concatenation of AIDs at the moment */
417
0
    return SC_ERROR_NOT_SUPPORTED;
418
419
0
  if (p1->len + p2->len > SC_MAX_PATH_SIZE)
420
0
    return SC_ERROR_INVALID_ARGUMENTS;
421
422
0
  memset(&tpath, 0, sizeof(sc_path_t));
423
0
  memcpy(tpath.value, p1->value, p1->len);
424
0
  memcpy(tpath.value + p1->len, p2->value, p2->len);
425
0
  tpath.len  = p1->len + p2->len;
426
0
  tpath.type = SC_PATH_TYPE_PATH;
427
  /* use 'index' and 'count' entry of the second path object */
428
0
  tpath.index = p2->index;
429
0
  tpath.count = p2->count;
430
  /* the result is currently always as path */
431
0
  tpath.type  = SC_PATH_TYPE_PATH;
432
433
0
  *d = tpath;
434
435
0
  return SC_SUCCESS;
436
0
}
437
438
const char *sc_print_path(const sc_path_t *path)
439
0
{
440
0
  static char buffer[SC_MAX_PATH_STRING_SIZE + SC_MAX_AID_STRING_SIZE];
441
442
0
  if (sc_path_print(buffer, sizeof(buffer), path) != SC_SUCCESS)
443
0
    buffer[0] = '\0';
444
445
0
  return buffer;
446
0
}
447
448
int sc_path_print(char *buf, size_t buflen, const sc_path_t *path)
449
0
{
450
0
  size_t i;
451
452
0
  if (buf == NULL || path == NULL)
453
0
    return SC_ERROR_INVALID_ARGUMENTS;
454
455
0
  if (buflen < path->len * 2 + path->aid.len * 2 + 3)
456
0
    return SC_ERROR_BUFFER_TOO_SMALL;
457
458
0
  buf[0] = '\0';
459
0
  if (path->aid.len)   {
460
0
    for (i = 0; i < path->aid.len; i++)
461
0
      snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->aid.value[i]);
462
0
    snprintf(buf + strlen(buf), buflen - strlen(buf), "::");
463
0
  }
464
465
0
  for (i = 0; i < path->len; i++)
466
0
    snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->value[i]);
467
0
  if (!path->aid.len && path->type == SC_PATH_TYPE_DF_NAME)
468
0
    snprintf(buf + strlen(buf), buflen - strlen(buf), "::");
469
470
0
  return SC_SUCCESS;
471
0
}
472
473
int sc_compare_path(const sc_path_t *path1, const sc_path_t *path2)
474
0
{
475
0
  return path1->len == path2->len
476
0
    && !memcmp(path1->value, path2->value, path1->len);
477
0
}
478
479
int sc_compare_path_prefix(const sc_path_t *prefix, const sc_path_t *path)
480
0
{
481
0
  sc_path_t tpath;
482
483
0
  if (prefix->len > path->len)
484
0
    return 0;
485
486
0
  tpath     = *path;
487
0
  tpath.len = prefix->len;
488
489
0
  return sc_compare_path(&tpath, prefix);
490
0
}
491
492
const sc_path_t *sc_get_mf_path(void)
493
0
{
494
0
  static const sc_path_t mf_path = {
495
0
    {0x3f, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2,
496
0
    0,
497
0
    0,
498
0
    SC_PATH_TYPE_PATH,
499
0
    {{0},0}
500
0
  };
501
0
  return &mf_path;
502
0
}
503
504
int sc_file_add_acl_entry(sc_file_t *file, unsigned int operation,
505
                          unsigned int method, unsigned long key_ref)
506
0
{
507
0
  sc_acl_entry_t *p, *_new;
508
509
0
  if (file == NULL || operation >= SC_MAX_AC_OPS) {
510
0
    return SC_ERROR_INVALID_ARGUMENTS;
511
0
  }
512
513
0
  switch (method) {
514
0
  case SC_AC_NEVER:
515
0
    sc_file_clear_acl_entries(file, operation);
516
0
    file->acl[operation] = (sc_acl_entry_t *) 1;
517
0
    return SC_SUCCESS;
518
0
  case SC_AC_NONE:
519
0
    sc_file_clear_acl_entries(file, operation);
520
0
    file->acl[operation] = (sc_acl_entry_t *) 2;
521
0
    return SC_SUCCESS;
522
0
  case SC_AC_UNKNOWN:
523
0
    sc_file_clear_acl_entries(file, operation);
524
0
    file->acl[operation] = (sc_acl_entry_t *) 3;
525
0
    return SC_SUCCESS;
526
0
  default:
527
    /* NONE and UNKNOWN get zapped when a new AC is added.
528
     * If the ACL is NEVER, additional entries will be
529
     * dropped silently. */
530
0
    if (file->acl[operation] == (sc_acl_entry_t *) 1)
531
0
      return SC_SUCCESS;
532
0
    if (file->acl[operation] == (sc_acl_entry_t *) 2
533
0
     || file->acl[operation] == (sc_acl_entry_t *) 3)
534
0
      file->acl[operation] = NULL;
535
0
  }
536
537
  /* If the entry is already present (e.g. due to the mapping)
538
   * of the card's AC with OpenSC's), don't add it again. */
539
0
  for (p = file->acl[operation]; p != NULL; p = p->next) {
540
0
    if ((p->method == method) && (p->key_ref == key_ref))
541
0
      return SC_SUCCESS;
542
0
  }
543
544
0
  _new = malloc(sizeof(sc_acl_entry_t));
545
0
  if (_new == NULL)
546
0
    return SC_ERROR_OUT_OF_MEMORY;
547
0
  _new->method = method;
548
0
  _new->key_ref = (unsigned)key_ref;
549
0
  _new->next = NULL;
550
551
0
  p = file->acl[operation];
552
0
  if (p == NULL) {
553
0
    file->acl[operation] = _new;
554
0
    return SC_SUCCESS;
555
0
  }
556
0
  while (p->next != NULL)
557
0
    p = p->next;
558
0
  p->next = _new;
559
560
0
  return SC_SUCCESS;
561
0
}
562
563
const sc_acl_entry_t * sc_file_get_acl_entry(const sc_file_t *file,
564
              unsigned int operation)
565
0
{
566
0
  sc_acl_entry_t *p;
567
0
  static const sc_acl_entry_t e_never = {
568
0
    SC_AC_NEVER, SC_AC_KEY_REF_NONE, NULL
569
0
  };
570
0
  static const sc_acl_entry_t e_none = {
571
0
    SC_AC_NONE, SC_AC_KEY_REF_NONE, NULL
572
0
  };
573
0
  static const sc_acl_entry_t e_unknown = {
574
0
    SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE, NULL
575
0
  };
576
577
0
  if (file == NULL || operation >= SC_MAX_AC_OPS) {
578
0
    return NULL;
579
0
  }
580
581
0
  p = file->acl[operation];
582
0
  if (p == (sc_acl_entry_t *) 1)
583
0
    return &e_never;
584
0
  if (p == (sc_acl_entry_t *) 2)
585
0
    return &e_none;
586
0
  if (p == (sc_acl_entry_t *) 3)
587
0
    return &e_unknown;
588
589
0
  return file->acl[operation];
590
0
}
591
592
void sc_file_clear_acl_entries(sc_file_t *file, unsigned int operation)
593
0
{
594
0
  sc_acl_entry_t *e;
595
596
0
  if (file == NULL || operation >= SC_MAX_AC_OPS) {
597
0
    return;
598
0
  }
599
600
0
  e = file->acl[operation];
601
0
  if (e == (sc_acl_entry_t *) 1 ||
602
0
      e == (sc_acl_entry_t *) 2 ||
603
0
      e == (sc_acl_entry_t *) 3) {
604
0
    file->acl[operation] = NULL;
605
0
    return;
606
0
  }
607
608
0
  while (e != NULL) {
609
0
    sc_acl_entry_t *tmp = e->next;
610
0
    free(e);
611
0
    e = tmp;
612
0
  }
613
0
  file->acl[operation] = NULL;
614
0
}
615
616
sc_file_t * sc_file_new(void)
617
0
{
618
0
  sc_file_t *file = (sc_file_t *)calloc(1, sizeof(sc_file_t));
619
0
  if (file == NULL)
620
0
    return NULL;
621
622
0
  file->magic = SC_FILE_MAGIC;
623
0
  return file;
624
0
}
625
626
void sc_file_free(sc_file_t *file)
627
0
{
628
0
  unsigned int i;
629
0
  if (file == NULL || !sc_file_valid(file))
630
0
    return;
631
0
  file->magic = 0;
632
0
  for (i = 0; i < SC_MAX_AC_OPS; i++)
633
0
    sc_file_clear_acl_entries(file, i);
634
0
  if (file->sec_attr)
635
0
    free(file->sec_attr);
636
0
  if (file->prop_attr)
637
0
    free(file->prop_attr);
638
0
  if (file->type_attr)
639
0
    free(file->type_attr);
640
0
  if (file->encoded_content)
641
0
    free(file->encoded_content);
642
0
  free(file);
643
0
}
644
645
void sc_file_dup(sc_file_t **dest, const sc_file_t *src)
646
0
{
647
0
  sc_file_t *newf;
648
0
  const sc_acl_entry_t *e;
649
0
  unsigned int op;
650
651
0
  *dest = NULL;
652
0
  if (!sc_file_valid(src))
653
0
    return;
654
0
  newf = sc_file_new();
655
0
  if (newf == NULL)
656
0
    return;
657
0
  *dest = newf;
658
659
0
  memcpy(&newf->path, &src->path, sizeof(struct sc_path));
660
0
  memcpy(&newf->name, &src->name, sizeof(src->name));
661
0
  newf->namelen = src->namelen;
662
0
  newf->type    = src->type;
663
0
  newf->shareable    = src->shareable;
664
0
  newf->ef_structure = src->ef_structure;
665
0
  newf->size    = src->size;
666
0
  newf->id      = src->id;
667
0
  newf->status  = src->status;
668
0
  for (op = 0; op < SC_MAX_AC_OPS; op++) {
669
0
    newf->acl[op] = NULL;
670
0
    e = sc_file_get_acl_entry(src, op);
671
0
    if (e != NULL) {
672
0
      if (sc_file_add_acl_entry(newf, op, e->method, e->key_ref) < 0)
673
0
        goto err;
674
0
    }
675
0
  }
676
0
  newf->record_length = src->record_length;
677
0
  newf->record_count  = src->record_count;
678
679
0
  if (sc_file_set_sec_attr(newf, src->sec_attr, src->sec_attr_len) < 0)
680
0
    goto err;
681
0
  if (sc_file_set_prop_attr(newf, src->prop_attr, src->prop_attr_len) < 0)
682
0
    goto err;
683
0
  if (sc_file_set_type_attr(newf, src->type_attr, src->type_attr_len) < 0)
684
0
    goto err;
685
0
  if (sc_file_set_content(newf, src->encoded_content, src->encoded_content_len) < 0)
686
0
    goto err;
687
0
  return;
688
0
err:
689
0
  sc_file_free(newf);
690
0
  *dest = NULL;
691
0
}
692
693
int sc_file_set_sec_attr(sc_file_t *file, const u8 *sec_attr,
694
       size_t sec_attr_len)
695
0
{
696
0
  u8 *tmp;
697
0
  if (!sc_file_valid(file)) {
698
0
    return SC_ERROR_INVALID_ARGUMENTS;
699
0
  }
700
701
0
  if (sec_attr == NULL || sec_attr_len == 0) {
702
0
    if (file->sec_attr != NULL)
703
0
      free(file->sec_attr);
704
0
    file->sec_attr = NULL;
705
0
    file->sec_attr_len = 0;
706
0
    return 0;
707
0
   }
708
0
  tmp = (u8 *) realloc(file->sec_attr, sec_attr_len);
709
0
  if (!tmp) {
710
0
    if (file->sec_attr)
711
0
      free(file->sec_attr);
712
0
    file->sec_attr     = NULL;
713
0
    file->sec_attr_len = 0;
714
0
    return SC_ERROR_OUT_OF_MEMORY;
715
0
  }
716
0
  file->sec_attr = tmp;
717
0
  memcpy(file->sec_attr, sec_attr, sec_attr_len);
718
0
  file->sec_attr_len = sec_attr_len;
719
720
0
  return 0;
721
0
}
722
723
int sc_file_set_prop_attr(sc_file_t *file, const u8 *prop_attr,
724
       size_t prop_attr_len)
725
0
{
726
0
  u8 *tmp;
727
0
  if (!sc_file_valid(file)) {
728
0
    return SC_ERROR_INVALID_ARGUMENTS;
729
0
  }
730
731
0
  if (prop_attr == NULL || prop_attr_len == 0) {
732
0
    if (file->prop_attr != NULL)
733
0
      free(file->prop_attr);
734
0
    file->prop_attr = NULL;
735
0
    file->prop_attr_len = 0;
736
0
    return SC_SUCCESS;
737
0
   }
738
0
  tmp = (u8 *) realloc(file->prop_attr, prop_attr_len);
739
0
  if (!tmp) {
740
0
    if (file->prop_attr)
741
0
      free(file->prop_attr);
742
0
    file->prop_attr = NULL;
743
0
    file->prop_attr_len = 0;
744
0
    return SC_ERROR_OUT_OF_MEMORY;
745
0
  }
746
0
  file->prop_attr = tmp;
747
0
  memcpy(file->prop_attr, prop_attr, prop_attr_len);
748
0
  file->prop_attr_len = prop_attr_len;
749
750
0
  return SC_SUCCESS;
751
0
}
752
753
int sc_file_set_type_attr(sc_file_t *file, const u8 *type_attr,
754
       size_t type_attr_len)
755
0
{
756
0
  u8 *tmp;
757
0
  if (!sc_file_valid(file)) {
758
0
    return SC_ERROR_INVALID_ARGUMENTS;
759
0
  }
760
761
0
  if (type_attr == NULL || type_attr_len == 0) {
762
0
    if (file->type_attr != NULL)
763
0
      free(file->type_attr);
764
0
    file->type_attr = NULL;
765
0
    file->type_attr_len = 0;
766
0
    return SC_SUCCESS;
767
0
   }
768
0
  tmp = (u8 *) realloc(file->type_attr, type_attr_len);
769
0
  if (!tmp) {
770
0
    if (file->type_attr)
771
0
      free(file->type_attr);
772
0
    file->type_attr = NULL;
773
0
    file->type_attr_len = 0;
774
0
    return SC_ERROR_OUT_OF_MEMORY;
775
0
  }
776
0
  file->type_attr = tmp;
777
0
  memcpy(file->type_attr, type_attr, type_attr_len);
778
0
  file->type_attr_len = type_attr_len;
779
780
0
  return SC_SUCCESS;
781
0
}
782
783
784
int sc_file_set_content(sc_file_t *file, const u8 *content,
785
       size_t content_len)
786
0
{
787
0
  u8 *tmp;
788
0
  if (!sc_file_valid(file)) {
789
0
    return SC_ERROR_INVALID_ARGUMENTS;
790
0
  }
791
792
0
  if (content == NULL || content_len == 0) {
793
0
    if (file->encoded_content != NULL)
794
0
      free(file->encoded_content);
795
0
    file->encoded_content = NULL;
796
0
    file->encoded_content_len = 0;
797
0
    return SC_SUCCESS;
798
0
  }
799
800
0
  tmp = (u8 *) realloc(file->encoded_content, content_len);
801
0
  if (!tmp) {
802
0
    if (file->encoded_content)
803
0
      free(file->encoded_content);
804
0
    file->encoded_content = NULL;
805
0
    file->encoded_content_len = 0;
806
0
    return SC_ERROR_OUT_OF_MEMORY;
807
0
  }
808
809
0
  file->encoded_content = tmp;
810
0
  memcpy(file->encoded_content, content, content_len);
811
0
  file->encoded_content_len = content_len;
812
813
0
  return SC_SUCCESS;
814
0
}
815
816
817
0
int sc_file_valid(const sc_file_t *file) {
818
0
  if (file == NULL)
819
0
    return 0;
820
0
  return file->magic == SC_FILE_MAGIC;
821
0
}
822
823
int _sc_parse_atr(sc_reader_t *reader)
824
0
{
825
0
  u8 *p = reader->atr.value;
826
0
  int atr_len = (int) reader->atr.len;
827
0
  int n_hist, x;
828
0
  int tx[4] = {-1, -1, -1, -1};
829
0
  int i, FI, DI;
830
0
  const int Fi_table[] = {
831
0
    372, 372, 558, 744, 1116, 1488, 1860, -1,
832
0
    -1, 512, 768, 1024, 1536, 2048, -1, -1 };
833
0
  const int f_table[] = {
834
0
    40, 50, 60, 80, 120, 160, 200, -1,
835
0
    -1, 50, 75, 100, 150, 200, -1, -1 };
836
0
  const int Di_table[] = {
837
0
    -1, 1, 2, 4, 8, 16, 32, -1,
838
0
    12, 20, -1, -1, -1, -1, -1, -1 };
839
840
0
  reader->atr_info.hist_bytes_len = 0;
841
0
  reader->atr_info.hist_bytes = NULL;
842
843
0
  if (atr_len == 0) {
844
0
    sc_log(reader->ctx, "empty ATR - card not present?\n");
845
0
    return SC_ERROR_INTERNAL;
846
0
  }
847
848
0
  if (p[0] != 0x3B && p[0] != 0x3F) {
849
0
    sc_log(reader->ctx, "invalid sync byte in ATR: 0x%02X\n", p[0]);
850
0
    return SC_ERROR_INTERNAL;
851
0
  }
852
0
  n_hist = p[1] & 0x0F;
853
0
  x = p[1] >> 4;
854
0
  p += 2;
855
0
  atr_len -= 2;
856
0
  for (i = 0; i < 4 && atr_len > 0; i++) {
857
0
                if (x & (1 << i)) {
858
0
                        tx[i] = *p;
859
0
                        p++;
860
0
                        atr_len--;
861
0
                } else
862
0
                        tx[i] = -1;
863
0
        }
864
0
  if (tx[0] >= 0) {
865
0
    reader->atr_info.FI = FI = tx[0] >> 4;
866
0
    reader->atr_info.DI = DI = tx[0] & 0x0F;
867
0
    reader->atr_info.Fi = Fi_table[FI];
868
0
    reader->atr_info.f = f_table[FI];
869
0
    reader->atr_info.Di = Di_table[DI];
870
0
  } else {
871
0
    reader->atr_info.Fi = -1;
872
0
    reader->atr_info.f = -1;
873
0
    reader->atr_info.Di = -1;
874
0
  }
875
0
  if (tx[2] >= 0)
876
0
    reader->atr_info.N = tx[3];
877
0
  else
878
0
    reader->atr_info.N = -1;
879
0
  while (tx[3] > 0 && tx[3] & 0xF0 && atr_len > 0) {
880
0
    x = tx[3] >> 4;
881
0
    for (i = 0; i < 4 && atr_len > 0; i++) {
882
0
                  if (x & (1 << i)) {
883
0
                          tx[i] = *p;
884
0
                          p++;
885
0
                          atr_len--;
886
0
                  } else
887
0
                          tx[i] = -1;
888
0
    }
889
0
  }
890
0
  if (atr_len <= 0)
891
0
    return SC_SUCCESS;
892
0
  if (n_hist > atr_len)
893
0
    n_hist = atr_len;
894
0
  reader->atr_info.hist_bytes_len = n_hist;
895
0
  reader->atr_info.hist_bytes = p;
896
0
  return SC_SUCCESS;
897
0
}
898
899
void *sc_mem_secure_alloc(size_t len)
900
0
{
901
0
  void *p;
902
903
#ifdef _WIN32
904
  p = VirtualAlloc(NULL, len, MEM_COMMIT, PAGE_READWRITE);
905
  if (p != NULL) {
906
    VirtualLock(p, len);
907
  }
908
#else
909
0
  p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
910
0
  if (p != NULL) {
911
0
    mlock(p, len);
912
0
  }
913
0
#endif
914
915
0
  return p;
916
0
}
917
918
void sc_mem_secure_free(void *ptr, size_t len)
919
0
{
920
#ifdef _WIN32
921
  VirtualUnlock(ptr, len);
922
  VirtualFree(ptr, 0, MEM_RELEASE);
923
#else
924
0
  munlock(ptr, len);
925
0
  munmap(ptr, len);
926
0
#endif
927
0
}
928
929
void sc_mem_clear(void *ptr, size_t len)
930
0
{
931
0
  if (len > 0)   {
932
#ifdef HAVE_MEMSET_S
933
    memset_s(ptr, len, 0, len);
934
#elif _WIN32
935
    SecureZeroMemory(ptr, len);
936
#elif HAVE_EXPLICIT_BZERO
937
    explicit_bzero(ptr, len);
938
#elif ENABLE_OPENSSL
939
    OPENSSL_cleanse(ptr, len);
940
#else
941
    memset(ptr, 0, len);
942
#endif
943
0
  }
944
0
}
945
946
int sc_mem_reverse(unsigned char *buf, size_t len)
947
0
{
948
0
  unsigned char ch;
949
0
  size_t ii;
950
951
0
  if (!buf || !len)
952
0
    return SC_ERROR_INVALID_ARGUMENTS;
953
954
0
  for (ii = 0; ii < len / 2; ii++)   {
955
0
    ch = *(buf + ii);
956
0
    *(buf + ii) = *(buf + len - 1 - ii);
957
0
    *(buf + len - 1 - ii) = ch;
958
0
  }
959
960
0
  return SC_SUCCESS;
961
0
}
962
963
static int
964
sc_remote_apdu_allocate(struct sc_remote_data *rdata,
965
    struct sc_remote_apdu **new_rapdu)
966
0
{
967
0
  struct sc_remote_apdu *rapdu = NULL, *rr;
968
969
0
  if (!rdata)
970
0
    return SC_ERROR_INVALID_ARGUMENTS;
971
972
0
  rapdu = calloc(1, sizeof(struct sc_remote_apdu));
973
0
  if (rapdu == NULL)
974
0
    return SC_ERROR_OUT_OF_MEMORY;
975
976
0
  rapdu->apdu.data = &rapdu->sbuf[0];
977
0
  rapdu->apdu.resp = &rapdu->rbuf[0];
978
0
  rapdu->apdu.resplen = sizeof(rapdu->rbuf);
979
980
0
  if (new_rapdu)
981
0
    *new_rapdu = rapdu;
982
983
0
  if (rdata->data == NULL)   {
984
0
    rdata->data = rapdu;
985
0
    rdata->length = 1;
986
0
    return SC_SUCCESS;
987
0
  }
988
989
0
  for (rr = rdata->data; rr->next; rr = rr->next)
990
0
    ;
991
0
  rr->next = rapdu;
992
0
  rdata->length++;
993
994
0
  return SC_SUCCESS;
995
0
}
996
997
static void
998
sc_remote_apdu_free (struct sc_remote_data *rdata)
999
0
{
1000
0
  struct sc_remote_apdu *rapdu = NULL;
1001
1002
0
  if (!rdata)
1003
0
    return;
1004
1005
0
  rapdu = rdata->data;
1006
0
  while(rapdu)   {
1007
0
    struct sc_remote_apdu *rr = rapdu->next;
1008
1009
0
    free(rapdu);
1010
0
    rapdu = rr;
1011
0
  }
1012
0
}
1013
1014
void sc_remote_data_init(struct sc_remote_data *rdata)
1015
0
{
1016
0
  if (!rdata)
1017
0
    return;
1018
0
  memset(rdata, 0, sizeof(struct sc_remote_data));
1019
1020
0
  rdata->alloc = sc_remote_apdu_allocate;
1021
0
  rdata->free = sc_remote_apdu_free;
1022
0
}
1023
1024
static unsigned long  sc_CRC_tab32[256];
1025
static int sc_CRC_tab32_initialized = 0;
1026
unsigned sc_crc32(const unsigned char *value, size_t len)
1027
0
{
1028
0
  size_t ii, jj;
1029
0
  unsigned long crc;
1030
0
  unsigned long index, long_c;
1031
1032
0
  if (!sc_CRC_tab32_initialized)   {
1033
0
    for (ii=0; ii<256; ii++) {
1034
0
      crc = (unsigned long) ii;
1035
0
      for (jj=0; jj<8; jj++) {
1036
0
        if ( crc & 0x00000001L )
1037
0
          crc = ( crc >> 1 ) ^ 0xEDB88320l;
1038
0
        else
1039
0
          crc =   crc >> 1;
1040
0
      }
1041
0
      sc_CRC_tab32[ii] = crc;
1042
0
    }
1043
0
    sc_CRC_tab32_initialized = 1;
1044
0
  }
1045
1046
0
  crc = 0xffffffffL;
1047
0
  for (ii=0; ii<len; ii++)   {
1048
0
    long_c = 0x000000ffL & (unsigned long) (*(value + ii));
1049
0
    index = crc ^ long_c;
1050
0
    crc = (crc >> 8) ^ sc_CRC_tab32[ index & 0xff ];
1051
0
  }
1052
1053
0
  crc ^= 0xffffffff;
1054
0
  return  crc%0xffff;
1055
0
}
1056
1057
const u8 *sc_compacttlv_find_tag(const u8 *buf, size_t len, u8 tag, size_t *outlen)
1058
0
{
1059
0
  if (buf != NULL) {
1060
0
    size_t idx;
1061
0
    u8 plain_tag = tag & 0xF0;
1062
0
    size_t expected_len = tag & 0x0F;
1063
1064
0
          for (idx = 0; idx < len; idx++) {
1065
0
      if ((buf[idx] & 0xF0) == plain_tag && idx + expected_len < len &&
1066
0
          (expected_len == 0 || expected_len == (buf[idx] & 0x0F))) {
1067
0
        if (outlen != NULL)
1068
0
          *outlen = buf[idx] & 0x0F;
1069
0
        return buf + (idx + 1);
1070
0
      }
1071
0
      idx += (buf[idx] & 0x0F);
1072
0
                }
1073
0
        }
1074
0
  return NULL;
1075
0
}
1076
1077
/**************************** mutex functions ************************/
1078
1079
int sc_mutex_create(const sc_context_t *ctx, void **mutex)
1080
0
{
1081
0
  if (ctx == NULL)
1082
0
    return SC_ERROR_INVALID_ARGUMENTS;
1083
0
  if (ctx->thread_ctx != NULL && ctx->thread_ctx->create_mutex != NULL)
1084
0
    return ctx->thread_ctx->create_mutex(mutex);
1085
0
  else
1086
0
    return SC_SUCCESS;
1087
0
}
1088
1089
int sc_mutex_lock(const sc_context_t *ctx, void *mutex)
1090
0
{
1091
0
  if (ctx == NULL)
1092
0
    return SC_ERROR_INVALID_ARGUMENTS;
1093
0
  if (ctx->thread_ctx != NULL && ctx->thread_ctx->lock_mutex != NULL)
1094
0
    return ctx->thread_ctx->lock_mutex(mutex);
1095
0
  else
1096
0
    return SC_SUCCESS;
1097
0
}
1098
1099
int sc_mutex_unlock(const sc_context_t *ctx, void *mutex)
1100
0
{
1101
0
  if (ctx == NULL)
1102
0
    return SC_ERROR_INVALID_ARGUMENTS;
1103
0
  if (ctx->thread_ctx != NULL && ctx->thread_ctx->unlock_mutex != NULL)
1104
0
    return ctx->thread_ctx->unlock_mutex(mutex);
1105
0
  else
1106
0
    return SC_SUCCESS;
1107
0
}
1108
1109
int sc_mutex_destroy(const sc_context_t *ctx, void *mutex)
1110
0
{
1111
0
  if (ctx == NULL)
1112
0
    return SC_ERROR_INVALID_ARGUMENTS;
1113
0
  if (ctx->thread_ctx != NULL && ctx->thread_ctx->destroy_mutex != NULL)
1114
0
    return ctx->thread_ctx->destroy_mutex(mutex);
1115
0
  else
1116
0
    return SC_SUCCESS;
1117
0
}
1118
1119
unsigned long sc_thread_id(const sc_context_t *ctx)
1120
0
{
1121
0
  if (ctx == NULL || ctx->thread_ctx == NULL ||
1122
0
      ctx->thread_ctx->thread_id == NULL)
1123
0
    return 0UL;
1124
0
  else
1125
0
    return ctx->thread_ctx->thread_id();
1126
0
}
1127
1128
void sc_free(void *p)
1129
0
{
1130
0
  free(p);
1131
0
}