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