/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 | 103k | { |
60 | 103k | return sc_version; |
61 | 103k | } |
62 | | |
63 | | int sc_hex_to_bin(const char *in, u8 *out, size_t *outlen) |
64 | 1.54M | { |
65 | 1.54M | const char *sc_hex_to_bin_separators = " :"; |
66 | 1.54M | if (in == NULL || out == NULL || outlen == NULL) { |
67 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
68 | 0 | } |
69 | | |
70 | 1.54M | int byte_needs_nibble = 0; |
71 | 1.54M | int r = SC_SUCCESS; |
72 | 1.54M | size_t left = *outlen; |
73 | 1.54M | u8 byte = 0; |
74 | 23.4M | while (*in != '\0' && 0 != left) { |
75 | 21.9M | char c = *in++; |
76 | 21.9M | u8 nibble; |
77 | 21.9M | if ('0' <= c && c <= '9') |
78 | 11.4M | nibble = c - '0'; |
79 | 10.4M | else if ('a' <= c && c <= 'f') |
80 | 2.39M | nibble = c - 'a' + 10; |
81 | 8.08M | else if ('A' <= c && c <= 'F') |
82 | 3.13M | nibble = c - 'A' + 10; |
83 | 4.94M | else { |
84 | 4.94M | if (strchr(sc_hex_to_bin_separators, (int) c)) { |
85 | 4.93M | if (byte_needs_nibble) { |
86 | 557 | r = SC_ERROR_INVALID_ARGUMENTS; |
87 | 557 | goto err; |
88 | 557 | } |
89 | 4.93M | continue; |
90 | 4.93M | } |
91 | 16.0k | r = SC_ERROR_INVALID_ARGUMENTS; |
92 | 16.0k | goto err; |
93 | 4.94M | } |
94 | | |
95 | 16.9M | if (byte_needs_nibble) { |
96 | 8.47M | byte |= nibble; |
97 | 8.47M | *out++ = (u8) byte; |
98 | 8.47M | left--; |
99 | 8.47M | byte_needs_nibble = 0; |
100 | 8.52M | } else { |
101 | 8.52M | byte = nibble << 4; |
102 | 8.52M | byte_needs_nibble = 1; |
103 | 8.52M | } |
104 | 16.9M | } |
105 | | |
106 | 1.53M | 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 | 36.8k | *out = (u8) byte>>4; |
110 | 36.8k | left--; |
111 | 36.8k | byte_needs_nibble = 0; |
112 | 36.8k | } |
113 | | |
114 | | /* for ease of implementation we only accept completely hexed bytes. */ |
115 | 1.53M | if (byte_needs_nibble) { |
116 | 5.16k | r = SC_ERROR_INVALID_ARGUMENTS; |
117 | 5.16k | goto err; |
118 | 5.16k | } |
119 | | |
120 | | /* skip all trailing separators to see if we missed something */ |
121 | 1.52M | while (*in != '\0') { |
122 | 993 | if (NULL == strchr(sc_hex_to_bin_separators, (int) *in)) |
123 | 382 | break; |
124 | 611 | in++; |
125 | 611 | } |
126 | 1.52M | if (*in != '\0') { |
127 | 382 | r = SC_ERROR_BUFFER_TOO_SMALL; |
128 | 382 | goto err; |
129 | 382 | } |
130 | | |
131 | 1.54M | err: |
132 | 1.54M | *outlen -= left; |
133 | 1.54M | return r; |
134 | 1.52M | } |
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 | 1.76M | { |
139 | 1.76M | if (in == NULL || out == NULL) { |
140 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
141 | 0 | } |
142 | | |
143 | 1.76M | if (in_sep > 0) { |
144 | 1.72M | if (out_len < in_len*3 || out_len < 1) |
145 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
146 | 1.72M | } else { |
147 | 45.9k | if (out_len < in_len*2 + 1) |
148 | 55 | return SC_ERROR_BUFFER_TOO_SMALL; |
149 | 45.9k | } |
150 | | |
151 | 1.76M | const char hex[] = "0123456789abcdef"; |
152 | 16.7M | while (in_len) { |
153 | 14.9M | unsigned char value = *in++; |
154 | 14.9M | *out++ = hex[(value >> 4) & 0xF]; |
155 | 14.9M | *out++ = hex[ value & 0xF]; |
156 | 14.9M | in_len--; |
157 | 14.9M | if (in_len && in_sep > 0) |
158 | 13.7M | *out++ = (char)in_sep; |
159 | 14.9M | } |
160 | 1.76M | *out = '\0'; |
161 | | |
162 | 1.76M | return SC_SUCCESS; |
163 | 1.76M | } |
164 | | |
165 | | /* |
166 | | * Right trim all non-printable characters |
167 | | */ |
168 | 43 | size_t sc_right_trim(u8 *buf, size_t len) { |
169 | | |
170 | 43 | size_t i; |
171 | | |
172 | 43 | if (!buf) |
173 | 0 | return 0; |
174 | | |
175 | 43 | if (len > 0) { |
176 | 724 | for(i = len-1; i > 0; i--) { |
177 | 709 | if(!isprint(buf[i])) { |
178 | 681 | buf[i] = '\0'; |
179 | 681 | len--; |
180 | 681 | continue; |
181 | 681 | } |
182 | 28 | break; |
183 | 709 | } |
184 | 43 | } |
185 | 43 | return len; |
186 | 43 | } |
187 | | |
188 | | u8 *ulong2bebytes(u8 *buf, unsigned long x) |
189 | 361k | { |
190 | 361k | if (buf != NULL) { |
191 | 361k | buf[3] = (u8) (x & 0xff); |
192 | 361k | buf[2] = (u8) ((x >> 8) & 0xff); |
193 | 361k | buf[1] = (u8) ((x >> 16) & 0xff); |
194 | 361k | buf[0] = (u8) ((x >> 24) & 0xff); |
195 | 361k | } |
196 | 361k | return buf; |
197 | 361k | } |
198 | | |
199 | | u8 *ushort2bebytes(u8 *buf, unsigned short x) |
200 | 26.8k | { |
201 | 26.8k | if (buf != NULL) { |
202 | 26.8k | buf[1] = (u8) (x & 0xff); |
203 | 26.8k | buf[0] = (u8) ((x >> 8) & 0xff); |
204 | 26.8k | } |
205 | 26.8k | return buf; |
206 | 26.8k | } |
207 | | |
208 | | unsigned long bebytes2ulong(const u8 *buf) |
209 | 665k | { |
210 | 665k | if (buf == NULL) |
211 | 0 | return 0UL; |
212 | 665k | return (unsigned long)buf[0] << 24 |
213 | 665k | | (unsigned long)buf[1] << 16 |
214 | 665k | | (unsigned long)buf[2] << 8 |
215 | 665k | | (unsigned long)buf[3]; |
216 | 665k | } |
217 | | |
218 | | unsigned short bebytes2ushort(const u8 *buf) |
219 | 1.04M | { |
220 | 1.04M | if (buf == NULL) |
221 | 0 | return 0U; |
222 | 1.04M | return (unsigned short)buf[0] << 8 |
223 | 1.04M | | (unsigned short)buf[1]; |
224 | 1.04M | } |
225 | | |
226 | | unsigned short lebytes2ushort(const u8 *buf) |
227 | 39.7k | { |
228 | 39.7k | if (buf == NULL) |
229 | 0 | return 0U; |
230 | 39.7k | return (unsigned short)buf[1] << 8 |
231 | 39.7k | | (unsigned short)buf[0]; |
232 | 39.7k | } |
233 | | |
234 | | unsigned long lebytes2ulong(const u8 *buf) |
235 | 3.59k | { |
236 | 3.59k | if (buf == NULL) |
237 | 0 | return 0UL; |
238 | 3.59k | return (unsigned long)buf[3] << 24 |
239 | 3.59k | | (unsigned long)buf[2] << 16 |
240 | 3.59k | | (unsigned long)buf[1] << 8 |
241 | 3.59k | | (unsigned long)buf[0]; |
242 | 3.59k | } |
243 | | |
244 | | void set_string(char **strp, const char *value) |
245 | 70.4k | { |
246 | 70.4k | if (strp == NULL) { |
247 | 0 | return; |
248 | 0 | } |
249 | | |
250 | 70.4k | free(*strp); |
251 | 70.4k | *strp = value ? strdup(value) : NULL; |
252 | 70.4k | } |
253 | | |
254 | | void sc_init_oid(struct sc_object_id *oid) |
255 | 356k | { |
256 | 356k | int ii; |
257 | | |
258 | 356k | if (!oid) |
259 | 0 | return; |
260 | 6.06M | for (ii=0; ii<SC_MAX_OBJECT_ID_OCTETS; ii++) |
261 | 5.70M | oid->value[ii] = -1; |
262 | 356k | } |
263 | | |
264 | | int sc_format_oid(struct sc_object_id *oid, const char *in) |
265 | 115k | { |
266 | 115k | int ii, ret = SC_ERROR_INVALID_ARGUMENTS; |
267 | 115k | const char *p; |
268 | 115k | char *q; |
269 | | |
270 | 115k | if (oid == NULL || in == NULL) |
271 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
272 | | |
273 | 115k | sc_init_oid(oid); |
274 | | |
275 | 115k | p = in; |
276 | 942k | for (ii=0; ii < SC_MAX_OBJECT_ID_OCTETS; ii++) { |
277 | 942k | oid->value[ii] = (int)strtol(p, &q, 10); |
278 | 942k | if (!*q) |
279 | 109k | break; |
280 | | |
281 | 832k | if (!(q[0] == '.' && isdigit((unsigned char)q[1]))) |
282 | 5.22k | goto out; |
283 | | |
284 | 827k | p = q + 1; |
285 | 827k | } |
286 | | |
287 | 109k | if (!sc_valid_oid(oid)) |
288 | 24 | goto out; |
289 | | |
290 | 109k | ret = SC_SUCCESS; |
291 | 115k | out: |
292 | 115k | if (ret) |
293 | 5.24k | sc_init_oid(oid); |
294 | | |
295 | 115k | return ret; |
296 | 109k | } |
297 | | |
298 | | int sc_compare_oid(const struct sc_object_id *oid1, const struct sc_object_id *oid2) |
299 | 290k | { |
300 | 290k | int i; |
301 | | |
302 | 290k | if (oid1 == NULL || oid2 == NULL) { |
303 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
304 | 0 | } |
305 | | |
306 | 822k | for (i = 0; i < SC_MAX_OBJECT_ID_OCTETS; i++) { |
307 | 822k | if (oid1->value[i] != oid2->value[i]) |
308 | 266k | return 0; |
309 | 555k | if (oid1->value[i] == -1) |
310 | 23.9k | break; |
311 | 555k | } |
312 | | |
313 | 23.9k | return 1; |
314 | 290k | } |
315 | | |
316 | | |
317 | | int sc_valid_oid(const struct sc_object_id *oid) |
318 | 135k | { |
319 | 135k | int ii; |
320 | | |
321 | 135k | if (!oid) |
322 | 0 | return 0; |
323 | 135k | if (oid->value[0] == -1 || oid->value[1] == -1) |
324 | 1.35k | return 0; |
325 | 134k | if (oid->value[0] > 2 || oid->value[1] > 39) |
326 | 25 | return 0; |
327 | 266k | for (ii=0;ii<SC_MAX_OBJECT_ID_OCTETS;ii++) |
328 | 258k | if (oid->value[ii]) |
329 | 126k | break; |
330 | 134k | if (ii==SC_MAX_OBJECT_ID_OCTETS) |
331 | 8.25k | return 0; |
332 | 126k | return 1; |
333 | 134k | } |
334 | | |
335 | | |
336 | | int sc_detect_card_presence(sc_reader_t *reader) |
337 | 1.11k | { |
338 | 1.11k | int r; |
339 | 1.11k | LOG_FUNC_CALLED(reader->ctx); |
340 | 1.11k | if (reader->ops->detect_card_presence == NULL) |
341 | 1.11k | 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 | 144k | { |
356 | 144k | if (path == NULL || id == NULL || id_len == 0 || id_len > SC_MAX_PATH_SIZE) |
357 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
358 | | |
359 | 144k | memset(path, 0, sizeof(*path)); |
360 | 144k | memcpy(path->value, id, id_len); |
361 | 144k | path->len = id_len; |
362 | 144k | path->type = type; |
363 | 144k | path->index = idx; |
364 | 144k | path->count = count; |
365 | | |
366 | 144k | return SC_SUCCESS; |
367 | 144k | } |
368 | | |
369 | | void sc_format_path(const char *str, sc_path_t *path) |
370 | 822k | { |
371 | 822k | int type = SC_PATH_TYPE_PATH; |
372 | | |
373 | 822k | if (path) { |
374 | 822k | memset(path, 0, sizeof(*path)); |
375 | 822k | if (*str == 'i' || *str == 'I') { |
376 | 951 | type = SC_PATH_TYPE_FILE_ID; |
377 | 951 | str++; |
378 | 951 | } |
379 | 822k | path->len = sizeof(path->value); |
380 | 822k | if (sc_hex_to_bin(str, path->value, &path->len) >= 0) { |
381 | 817k | path->type = type; |
382 | 817k | } |
383 | 822k | path->count = -1; |
384 | 822k | } |
385 | 822k | } |
386 | | |
387 | | int sc_append_path(sc_path_t *dest, const sc_path_t *src) |
388 | 1 | { |
389 | 1 | return sc_concatenate_path(dest, dest, src); |
390 | 1 | } |
391 | | |
392 | | int sc_append_path_id(sc_path_t *dest, const u8 *id, size_t idlen) |
393 | 1.55M | { |
394 | 1.55M | if (dest->len + idlen > SC_MAX_PATH_SIZE) |
395 | 1.25M | return SC_ERROR_INVALID_ARGUMENTS; |
396 | 299k | memcpy(dest->value + dest->len, id, idlen); |
397 | 299k | dest->len += idlen; |
398 | 299k | return SC_SUCCESS; |
399 | 1.55M | } |
400 | | |
401 | | int sc_append_file_id(sc_path_t *dest, unsigned int fid) |
402 | 1.55M | { |
403 | 1.55M | u8 id[2] = { fid >> 8, fid & 0xff }; |
404 | | |
405 | 1.55M | return sc_append_path_id(dest, id, 2); |
406 | 1.55M | } |
407 | | |
408 | | int sc_concatenate_path(sc_path_t *d, const sc_path_t *p1, const sc_path_t *p2) |
409 | 105k | { |
410 | 105k | sc_path_t tpath; |
411 | | |
412 | 105k | if (d == NULL || p1 == NULL || p2 == NULL) |
413 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
414 | | |
415 | 105k | 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 | 105k | if (p1->len + p2->len > SC_MAX_PATH_SIZE) |
420 | 38 | return SC_ERROR_INVALID_ARGUMENTS; |
421 | | |
422 | 105k | memset(&tpath, 0, sizeof(sc_path_t)); |
423 | 105k | memcpy(tpath.value, p1->value, p1->len); |
424 | 105k | memcpy(tpath.value + p1->len, p2->value, p2->len); |
425 | 105k | tpath.len = p1->len + p2->len; |
426 | 105k | tpath.type = SC_PATH_TYPE_PATH; |
427 | | /* use 'index' and 'count' entry of the second path object */ |
428 | 105k | tpath.index = p2->index; |
429 | 105k | tpath.count = p2->count; |
430 | | /* the result is currently always as path */ |
431 | 105k | tpath.type = SC_PATH_TYPE_PATH; |
432 | | |
433 | 105k | *d = tpath; |
434 | | |
435 | 105k | return SC_SUCCESS; |
436 | 105k | } |
437 | | |
438 | | const char *sc_print_path(const sc_path_t *path) |
439 | 2.68M | { |
440 | 2.68M | static char buffer[SC_MAX_PATH_STRING_SIZE + SC_MAX_AID_STRING_SIZE]; |
441 | | |
442 | 2.68M | if (sc_path_print(buffer, sizeof(buffer), path) != SC_SUCCESS) |
443 | 0 | buffer[0] = '\0'; |
444 | | |
445 | 2.68M | return buffer; |
446 | 2.68M | } |
447 | | |
448 | | int sc_path_print(char *buf, size_t buflen, const sc_path_t *path) |
449 | 3.69M | { |
450 | 3.69M | size_t i; |
451 | | |
452 | 3.69M | if (buf == NULL || path == NULL) |
453 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
454 | | |
455 | 3.69M | if (buflen < path->len * 2 + path->aid.len * 2 + 3) |
456 | 3.11k | return SC_ERROR_BUFFER_TOO_SMALL; |
457 | | |
458 | 3.69M | buf[0] = '\0'; |
459 | 3.69M | if (path->aid.len) { |
460 | 7.54M | for (i = 0; i < path->aid.len; i++) |
461 | 6.60M | snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->aid.value[i]); |
462 | 942k | snprintf(buf + strlen(buf), buflen - strlen(buf), "::"); |
463 | 942k | } |
464 | | |
465 | 17.7M | for (i = 0; i < path->len; i++) |
466 | 14.0M | snprintf(buf + strlen(buf), buflen - strlen(buf), "%02x", path->value[i]); |
467 | 3.69M | if (!path->aid.len && path->type == SC_PATH_TYPE_DF_NAME) |
468 | 177k | snprintf(buf + strlen(buf), buflen - strlen(buf), "::"); |
469 | | |
470 | 3.69M | return SC_SUCCESS; |
471 | 3.69M | } |
472 | | |
473 | | int sc_compare_path(const sc_path_t *path1, const sc_path_t *path2) |
474 | 131k | { |
475 | 131k | return path1->len == path2->len |
476 | 131k | && !memcmp(path1->value, path2->value, path1->len); |
477 | 131k | } |
478 | | |
479 | | int sc_compare_path_prefix(const sc_path_t *prefix, const sc_path_t *path) |
480 | 84.8k | { |
481 | 84.8k | sc_path_t tpath; |
482 | | |
483 | 84.8k | if (prefix->len > path->len) |
484 | 3.91k | return 0; |
485 | | |
486 | 80.9k | tpath = *path; |
487 | 80.9k | tpath.len = prefix->len; |
488 | | |
489 | 80.9k | return sc_compare_path(&tpath, prefix); |
490 | 84.8k | } |
491 | | |
492 | | const sc_path_t *sc_get_mf_path(void) |
493 | 106k | { |
494 | 106k | static const sc_path_t mf_path = { |
495 | 106k | {0x3f, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 2, |
496 | 106k | 0, |
497 | 106k | 0, |
498 | 106k | SC_PATH_TYPE_PATH, |
499 | 106k | {{0},0} |
500 | 106k | }; |
501 | 106k | return &mf_path; |
502 | 106k | } |
503 | | |
504 | | int sc_file_add_acl_entry(sc_file_t *file, unsigned int operation, |
505 | | unsigned int method, unsigned long key_ref) |
506 | 7.38M | { |
507 | 7.38M | sc_acl_entry_t *p, *_new; |
508 | | |
509 | 7.38M | if (file == NULL || operation >= SC_MAX_AC_OPS) { |
510 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
511 | 0 | } |
512 | | |
513 | 7.38M | switch (method) { |
514 | 3.37M | case SC_AC_NEVER: |
515 | 3.37M | sc_file_clear_acl_entries(file, operation); |
516 | 3.37M | file->acl[operation] = (sc_acl_entry_t *) 1; |
517 | 3.37M | return SC_SUCCESS; |
518 | 2.94M | case SC_AC_NONE: |
519 | 2.94M | sc_file_clear_acl_entries(file, operation); |
520 | 2.94M | file->acl[operation] = (sc_acl_entry_t *) 2; |
521 | 2.94M | return SC_SUCCESS; |
522 | 16.5k | case SC_AC_UNKNOWN: |
523 | 16.5k | sc_file_clear_acl_entries(file, operation); |
524 | 16.5k | file->acl[operation] = (sc_acl_entry_t *) 3; |
525 | 16.5k | return SC_SUCCESS; |
526 | 1.04M | 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 | 1.04M | if (file->acl[operation] == (sc_acl_entry_t *) 1) |
531 | 256 | return SC_SUCCESS; |
532 | 1.04M | if (file->acl[operation] == (sc_acl_entry_t *) 2 |
533 | 1.04M | || file->acl[operation] == (sc_acl_entry_t *) 3) |
534 | 19.0k | file->acl[operation] = NULL; |
535 | 7.38M | } |
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 | 1.44M | for (p = file->acl[operation]; p != NULL; p = p->next) { |
540 | 416k | if ((p->method == method) && (p->key_ref == key_ref)) |
541 | 18.4k | return SC_SUCCESS; |
542 | 416k | } |
543 | | |
544 | 1.02M | _new = malloc(sizeof(sc_acl_entry_t)); |
545 | 1.02M | if (_new == NULL) |
546 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
547 | 1.02M | _new->method = method; |
548 | 1.02M | _new->key_ref = (unsigned)key_ref; |
549 | 1.02M | _new->next = NULL; |
550 | | |
551 | 1.02M | p = file->acl[operation]; |
552 | 1.02M | if (p == NULL) { |
553 | 940k | file->acl[operation] = _new; |
554 | 940k | return SC_SUCCESS; |
555 | 940k | } |
556 | 387k | while (p->next != NULL) |
557 | 300k | p = p->next; |
558 | 87.3k | p->next = _new; |
559 | | |
560 | 87.3k | return SC_SUCCESS; |
561 | 1.02M | } |
562 | | |
563 | | const sc_acl_entry_t * sc_file_get_acl_entry(const sc_file_t *file, |
564 | | unsigned int operation) |
565 | 3.49M | { |
566 | 3.49M | sc_acl_entry_t *p; |
567 | 3.49M | static const sc_acl_entry_t e_never = { |
568 | 3.49M | SC_AC_NEVER, SC_AC_KEY_REF_NONE, NULL |
569 | 3.49M | }; |
570 | 3.49M | static const sc_acl_entry_t e_none = { |
571 | 3.49M | SC_AC_NONE, SC_AC_KEY_REF_NONE, NULL |
572 | 3.49M | }; |
573 | 3.49M | static const sc_acl_entry_t e_unknown = { |
574 | 3.49M | SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE, NULL |
575 | 3.49M | }; |
576 | | |
577 | 3.49M | if (file == NULL || operation >= SC_MAX_AC_OPS) { |
578 | 28 | return NULL; |
579 | 28 | } |
580 | | |
581 | 3.49M | p = file->acl[operation]; |
582 | 3.49M | if (p == (sc_acl_entry_t *) 1) |
583 | 110k | return &e_never; |
584 | 3.38M | if (p == (sc_acl_entry_t *) 2) |
585 | 743k | return &e_none; |
586 | 2.63M | if (p == (sc_acl_entry_t *) 3) |
587 | 9.72k | return &e_unknown; |
588 | | |
589 | 2.62M | return file->acl[operation]; |
590 | 2.63M | } |
591 | | |
592 | | void sc_file_clear_acl_entries(sc_file_t *file, unsigned int operation) |
593 | 67.9M | { |
594 | 67.9M | sc_acl_entry_t *e; |
595 | | |
596 | 67.9M | if (file == NULL || operation >= SC_MAX_AC_OPS) { |
597 | 0 | return; |
598 | 0 | } |
599 | | |
600 | 67.9M | e = file->acl[operation]; |
601 | 67.9M | if (e == (sc_acl_entry_t *) 1 || |
602 | 67.9M | e == (sc_acl_entry_t *) 2 || |
603 | 67.9M | e == (sc_acl_entry_t *) 3) { |
604 | 6.31M | file->acl[operation] = NULL; |
605 | 6.31M | return; |
606 | 6.31M | } |
607 | | |
608 | 62.6M | while (e != NULL) { |
609 | 1.02M | sc_acl_entry_t *tmp = e->next; |
610 | 1.02M | free(e); |
611 | 1.02M | e = tmp; |
612 | 1.02M | } |
613 | 61.6M | file->acl[operation] = NULL; |
614 | 61.6M | } |
615 | | |
616 | | sc_file_t * sc_file_new(void) |
617 | 1.98M | { |
618 | 1.98M | sc_file_t *file = (sc_file_t *)calloc(1, sizeof(sc_file_t)); |
619 | 1.98M | if (file == NULL) |
620 | 0 | return NULL; |
621 | | |
622 | 1.98M | file->magic = SC_FILE_MAGIC; |
623 | 1.98M | return file; |
624 | 1.98M | } |
625 | | |
626 | | void sc_file_free(sc_file_t *file) |
627 | 3.42M | { |
628 | 3.42M | unsigned int i; |
629 | 3.42M | if (file == NULL || !sc_file_valid(file)) |
630 | 1.43M | return; |
631 | 1.98M | file->magic = 0; |
632 | 63.4M | for (i = 0; i < SC_MAX_AC_OPS; i++) |
633 | 61.4M | sc_file_clear_acl_entries(file, i); |
634 | 1.98M | if (file->sec_attr) |
635 | 24.9k | free(file->sec_attr); |
636 | 1.98M | if (file->prop_attr) |
637 | 16.6k | free(file->prop_attr); |
638 | 1.98M | if (file->type_attr) |
639 | 36.0k | free(file->type_attr); |
640 | 1.98M | if (file->encoded_content) |
641 | 557 | free(file->encoded_content); |
642 | 1.98M | free(file); |
643 | 1.98M | } |
644 | | |
645 | | void sc_file_dup(sc_file_t **dest, const sc_file_t *src) |
646 | 103k | { |
647 | 103k | sc_file_t *newf; |
648 | 103k | const sc_acl_entry_t *e; |
649 | 103k | unsigned int op; |
650 | | |
651 | 103k | *dest = NULL; |
652 | 103k | if (!sc_file_valid(src)) |
653 | 0 | return; |
654 | 103k | newf = sc_file_new(); |
655 | 103k | if (newf == NULL) |
656 | 0 | return; |
657 | 103k | *dest = newf; |
658 | | |
659 | 103k | memcpy(&newf->path, &src->path, sizeof(struct sc_path)); |
660 | 103k | memcpy(&newf->name, &src->name, sizeof(src->name)); |
661 | 103k | newf->namelen = src->namelen; |
662 | 103k | newf->type = src->type; |
663 | 103k | newf->shareable = src->shareable; |
664 | 103k | newf->ef_structure = src->ef_structure; |
665 | 103k | newf->size = src->size; |
666 | 103k | newf->id = src->id; |
667 | 103k | newf->status = src->status; |
668 | 3.31M | for (op = 0; op < SC_MAX_AC_OPS; op++) { |
669 | 3.20M | newf->acl[op] = NULL; |
670 | 3.20M | e = sc_file_get_acl_entry(src, op); |
671 | 3.20M | if (e != NULL) { |
672 | 654k | if (sc_file_add_acl_entry(newf, op, e->method, e->key_ref) < 0) |
673 | 0 | goto err; |
674 | 654k | } |
675 | 3.20M | } |
676 | 103k | newf->record_length = src->record_length; |
677 | 103k | newf->record_count = src->record_count; |
678 | | |
679 | 103k | if (sc_file_set_sec_attr(newf, src->sec_attr, src->sec_attr_len) < 0) |
680 | 0 | goto err; |
681 | 103k | if (sc_file_set_prop_attr(newf, src->prop_attr, src->prop_attr_len) < 0) |
682 | 0 | goto err; |
683 | 103k | if (sc_file_set_type_attr(newf, src->type_attr, src->type_attr_len) < 0) |
684 | 0 | goto err; |
685 | 103k | if (sc_file_set_content(newf, src->encoded_content, src->encoded_content_len) < 0) |
686 | 0 | goto err; |
687 | 103k | return; |
688 | 103k | 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 | 130k | { |
696 | 130k | u8 *tmp; |
697 | 130k | if (!sc_file_valid(file)) { |
698 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
699 | 0 | } |
700 | | |
701 | 130k | if (sec_attr == NULL || sec_attr_len == 0) { |
702 | 105k | if (file->sec_attr != NULL) |
703 | 405 | free(file->sec_attr); |
704 | 105k | file->sec_attr = NULL; |
705 | 105k | file->sec_attr_len = 0; |
706 | 105k | return 0; |
707 | 105k | } |
708 | 25.6k | tmp = (u8 *) realloc(file->sec_attr, sec_attr_len); |
709 | 25.6k | 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 | 25.6k | file->sec_attr = tmp; |
717 | 25.6k | memcpy(file->sec_attr, sec_attr, sec_attr_len); |
718 | 25.6k | file->sec_attr_len = sec_attr_len; |
719 | | |
720 | 25.6k | return 0; |
721 | 25.6k | } |
722 | | |
723 | | int sc_file_set_prop_attr(sc_file_t *file, const u8 *prop_attr, |
724 | | size_t prop_attr_len) |
725 | 125k | { |
726 | 125k | u8 *tmp; |
727 | 125k | if (!sc_file_valid(file)) { |
728 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
729 | 0 | } |
730 | | |
731 | 125k | if (prop_attr == NULL || prop_attr_len == 0) { |
732 | 107k | if (file->prop_attr != NULL) |
733 | 612 | free(file->prop_attr); |
734 | 107k | file->prop_attr = NULL; |
735 | 107k | file->prop_attr_len = 0; |
736 | 107k | return SC_SUCCESS; |
737 | 107k | } |
738 | 17.6k | tmp = (u8 *) realloc(file->prop_attr, prop_attr_len); |
739 | 17.6k | 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 | 17.6k | file->prop_attr = tmp; |
747 | 17.6k | memcpy(file->prop_attr, prop_attr, prop_attr_len); |
748 | 17.6k | file->prop_attr_len = prop_attr_len; |
749 | | |
750 | 17.6k | return SC_SUCCESS; |
751 | 17.6k | } |
752 | | |
753 | | int sc_file_set_type_attr(sc_file_t *file, const u8 *type_attr, |
754 | | size_t type_attr_len) |
755 | 136k | { |
756 | 136k | u8 *tmp; |
757 | 136k | if (!sc_file_valid(file)) { |
758 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
759 | 0 | } |
760 | | |
761 | 136k | if (type_attr == NULL || type_attr_len == 0) { |
762 | 97.9k | if (file->type_attr != NULL) |
763 | 0 | free(file->type_attr); |
764 | 97.9k | file->type_attr = NULL; |
765 | 97.9k | file->type_attr_len = 0; |
766 | 97.9k | return SC_SUCCESS; |
767 | 97.9k | } |
768 | 38.9k | tmp = (u8 *) realloc(file->type_attr, type_attr_len); |
769 | 38.9k | 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 | 38.9k | file->type_attr = tmp; |
777 | 38.9k | memcpy(file->type_attr, type_attr, type_attr_len); |
778 | 38.9k | file->type_attr_len = type_attr_len; |
779 | | |
780 | 38.9k | return SC_SUCCESS; |
781 | 38.9k | } |
782 | | |
783 | | |
784 | | int sc_file_set_content(sc_file_t *file, const u8 *content, |
785 | | size_t content_len) |
786 | 103k | { |
787 | 103k | u8 *tmp; |
788 | 103k | if (!sc_file_valid(file)) { |
789 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
790 | 0 | } |
791 | | |
792 | 103k | if (content == NULL || content_len == 0) { |
793 | 103k | if (file->encoded_content != NULL) |
794 | 0 | free(file->encoded_content); |
795 | 103k | file->encoded_content = NULL; |
796 | 103k | file->encoded_content_len = 0; |
797 | 103k | return SC_SUCCESS; |
798 | 103k | } |
799 | | |
800 | 525 | tmp = (u8 *) realloc(file->encoded_content, content_len); |
801 | 525 | 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 | 525 | file->encoded_content = tmp; |
810 | 525 | memcpy(file->encoded_content, content, content_len); |
811 | 525 | file->encoded_content_len = content_len; |
812 | | |
813 | 525 | return SC_SUCCESS; |
814 | 525 | } |
815 | | |
816 | | |
817 | 2.58M | int sc_file_valid(const sc_file_t *file) { |
818 | 2.58M | if (file == NULL) |
819 | 0 | return 0; |
820 | 2.58M | return file->magic == SC_FILE_MAGIC; |
821 | 2.58M | } |
822 | | |
823 | | int _sc_parse_atr(sc_reader_t *reader) |
824 | 103k | { |
825 | 103k | u8 *p = reader->atr.value; |
826 | 103k | int atr_len = (int) reader->atr.len; |
827 | 103k | int n_hist, x; |
828 | 103k | int tx[4] = {-1, -1, -1, -1}; |
829 | 103k | int i, FI, DI; |
830 | 103k | const int Fi_table[] = { |
831 | 103k | 372, 372, 558, 744, 1116, 1488, 1860, -1, |
832 | 103k | -1, 512, 768, 1024, 1536, 2048, -1, -1 }; |
833 | 103k | const int f_table[] = { |
834 | 103k | 40, 50, 60, 80, 120, 160, 200, -1, |
835 | 103k | -1, 50, 75, 100, 150, 200, -1, -1 }; |
836 | 103k | const int Di_table[] = { |
837 | 103k | -1, 1, 2, 4, 8, 16, 32, -1, |
838 | 103k | 12, 20, -1, -1, -1, -1, -1, -1 }; |
839 | | |
840 | 103k | reader->atr_info.hist_bytes_len = 0; |
841 | 103k | reader->atr_info.hist_bytes = NULL; |
842 | | |
843 | 103k | if (atr_len == 0) { |
844 | 34.8k | sc_log(reader->ctx, "empty ATR - card not present?\n"); |
845 | 34.8k | return SC_ERROR_INTERNAL; |
846 | 34.8k | } |
847 | | |
848 | 68.7k | if (p[0] != 0x3B && p[0] != 0x3F) { |
849 | 7.97k | sc_log(reader->ctx, "invalid sync byte in ATR: 0x%02X\n", p[0]); |
850 | 7.97k | return SC_ERROR_INTERNAL; |
851 | 7.97k | } |
852 | 60.8k | n_hist = p[1] & 0x0F; |
853 | 60.8k | x = p[1] >> 4; |
854 | 60.8k | p += 2; |
855 | 60.8k | atr_len -= 2; |
856 | 303k | for (i = 0; i < 4 && atr_len > 0; i++) { |
857 | 242k | if (x & (1 << i)) { |
858 | 158k | tx[i] = *p; |
859 | 158k | p++; |
860 | 158k | atr_len--; |
861 | 158k | } else |
862 | 84.5k | tx[i] = -1; |
863 | 242k | } |
864 | 60.8k | if (tx[0] >= 0) { |
865 | 51.0k | reader->atr_info.FI = FI = tx[0] >> 4; |
866 | 51.0k | reader->atr_info.DI = DI = tx[0] & 0x0F; |
867 | 51.0k | reader->atr_info.Fi = Fi_table[FI]; |
868 | 51.0k | reader->atr_info.f = f_table[FI]; |
869 | 51.0k | reader->atr_info.Di = Di_table[DI]; |
870 | 51.0k | } else { |
871 | 9.76k | reader->atr_info.Fi = -1; |
872 | 9.76k | reader->atr_info.f = -1; |
873 | 9.76k | reader->atr_info.Di = -1; |
874 | 9.76k | } |
875 | 60.8k | if (tx[2] >= 0) |
876 | 38.9k | reader->atr_info.N = tx[3]; |
877 | 21.8k | else |
878 | 21.8k | reader->atr_info.N = -1; |
879 | 132k | while (tx[3] > 0 && tx[3] & 0xF0 && atr_len > 0) { |
880 | 71.9k | x = tx[3] >> 4; |
881 | 359k | for (i = 0; i < 4 && atr_len > 0; i++) { |
882 | 287k | if (x & (1 << i)) { |
883 | 110k | tx[i] = *p; |
884 | 110k | p++; |
885 | 110k | atr_len--; |
886 | 110k | } else |
887 | 177k | tx[i] = -1; |
888 | 287k | } |
889 | 71.9k | } |
890 | 60.8k | if (atr_len <= 0) |
891 | 628 | return SC_SUCCESS; |
892 | 60.1k | if (n_hist > atr_len) |
893 | 3.83k | n_hist = atr_len; |
894 | 60.1k | reader->atr_info.hist_bytes_len = n_hist; |
895 | 60.1k | reader->atr_info.hist_bytes = p; |
896 | 60.1k | return SC_SUCCESS; |
897 | 60.8k | } |
898 | | |
899 | | void *sc_mem_secure_alloc(size_t len) |
900 | 41.1k | { |
901 | 41.1k | 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 | 41.1k | p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
910 | 41.1k | if (p != NULL) { |
911 | 41.1k | mlock(p, len); |
912 | 41.1k | } |
913 | 41.1k | #endif |
914 | | |
915 | 41.1k | return p; |
916 | 41.1k | } |
917 | | |
918 | | void sc_mem_secure_free(void *ptr, size_t len) |
919 | 42.2k | { |
920 | | #ifdef _WIN32 |
921 | | VirtualUnlock(ptr, len); |
922 | | VirtualFree(ptr, 0, MEM_RELEASE); |
923 | | #else |
924 | 42.2k | munlock(ptr, len); |
925 | 42.2k | munmap(ptr, len); |
926 | 42.2k | #endif |
927 | 42.2k | } |
928 | | |
929 | | void sc_mem_clear(void *ptr, size_t len) |
930 | 432k | { |
931 | 432k | 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 | 431k | } |
944 | 432k | } |
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 | 6.23k | { |
1059 | 6.23k | if (buf != NULL) { |
1060 | 6.23k | size_t idx; |
1061 | 6.23k | u8 plain_tag = tag & 0xF0; |
1062 | 6.23k | size_t expected_len = tag & 0x0F; |
1063 | | |
1064 | 89.3k | for (idx = 0; idx < len; idx++) { |
1065 | 85.0k | if ((buf[idx] & 0xF0) == plain_tag && idx + expected_len < len && |
1066 | 85.0k | (expected_len == 0 || expected_len == (buf[idx] & 0x0F))) { |
1067 | 1.90k | if (outlen != NULL) |
1068 | 1.38k | *outlen = buf[idx] & 0x0F; |
1069 | 1.90k | return buf + (idx + 1); |
1070 | 1.90k | } |
1071 | 83.1k | idx += (buf[idx] & 0x0F); |
1072 | 83.1k | } |
1073 | 6.23k | } |
1074 | 4.33k | return NULL; |
1075 | 6.23k | } |
1076 | | |
1077 | | /**************************** mutex functions ************************/ |
1078 | | |
1079 | | int sc_mutex_create(const sc_context_t *ctx, void **mutex) |
1080 | 207k | { |
1081 | 207k | if (ctx == NULL) |
1082 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1083 | 207k | if (ctx->thread_ctx != NULL && ctx->thread_ctx->create_mutex != NULL) |
1084 | 30.3k | return ctx->thread_ctx->create_mutex(mutex); |
1085 | 177k | else |
1086 | 177k | return SC_SUCCESS; |
1087 | 207k | } |
1088 | | |
1089 | | int sc_mutex_lock(const sc_context_t *ctx, void *mutex) |
1090 | 12.4M | { |
1091 | 12.4M | if (ctx == NULL) |
1092 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1093 | 12.4M | if (ctx->thread_ctx != NULL && ctx->thread_ctx->lock_mutex != NULL) |
1094 | 1.08M | return ctx->thread_ctx->lock_mutex(mutex); |
1095 | 11.4M | else |
1096 | 11.4M | return SC_SUCCESS; |
1097 | 12.4M | } |
1098 | | |
1099 | | int sc_mutex_unlock(const sc_context_t *ctx, void *mutex) |
1100 | 12.4M | { |
1101 | 12.4M | if (ctx == NULL) |
1102 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1103 | 12.4M | if (ctx->thread_ctx != NULL && ctx->thread_ctx->unlock_mutex != NULL) |
1104 | 1.08M | return ctx->thread_ctx->unlock_mutex(mutex); |
1105 | 11.4M | else |
1106 | 11.4M | return SC_SUCCESS; |
1107 | 12.4M | } |
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 | } |