/src/opensc/src/libopensc/ef-gdo.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * ef-atr.c: Stuff for handling EF(GDO) |
3 | | * |
4 | | * Copyright (C) 2017 Frank Morgner <frankmorgner@gmail.com> |
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 | | #ifdef HAVE_CONFIG_H |
21 | | #include "config.h" |
22 | | #endif |
23 | | |
24 | | #include "asn1.h" |
25 | | #include "internal.h" |
26 | | #include <stdlib.h> |
27 | | #include <string.h> |
28 | | |
29 | | static int |
30 | | sc_parse_ef_gdo_content(const unsigned char *gdo, size_t gdo_len, |
31 | | unsigned char *iccsn, size_t *iccsn_len, |
32 | | unsigned char *chn, size_t *chn_len) |
33 | 61 | { |
34 | 61 | int r = SC_SUCCESS, iccsn_found = 0, chn_found = 0; |
35 | 61 | const unsigned char *p = gdo; |
36 | 61 | size_t left = gdo_len; |
37 | | |
38 | 471 | while (left >= 2) { |
39 | 446 | unsigned int cla, tag; |
40 | 446 | size_t tag_len; |
41 | | |
42 | 446 | r = sc_asn1_read_tag(&p, left, &cla, &tag, &tag_len); |
43 | 446 | if (r != SC_SUCCESS) { |
44 | 17 | if (r == SC_ERROR_ASN1_END_OF_CONTENTS) { |
45 | | /* not enough data */ |
46 | 15 | r = SC_SUCCESS; |
47 | 15 | } |
48 | 17 | break; |
49 | 17 | } |
50 | 429 | if (p == NULL) { |
51 | | /* done parsing */ |
52 | 19 | break; |
53 | 19 | } |
54 | | |
55 | 410 | if (cla == SC_ASN1_TAG_APPLICATION) { |
56 | 324 | switch (tag) { |
57 | 67 | case 0x1A: |
58 | 67 | iccsn_found = 1; |
59 | 67 | if (iccsn && iccsn_len) { |
60 | 67 | memcpy(iccsn, p, MIN(tag_len, *iccsn_len)); |
61 | 67 | *iccsn_len = MIN(tag_len, *iccsn_len); |
62 | 67 | } |
63 | 67 | break; |
64 | 1 | case 0x1F20: |
65 | 1 | chn_found = 1; |
66 | 1 | if (chn && chn_len) { |
67 | 0 | memcpy(chn, p, MIN(tag_len, *chn_len)); |
68 | 0 | *chn_len = MIN(tag_len, *chn_len); |
69 | 0 | } |
70 | 1 | break; |
71 | 324 | } |
72 | 324 | } |
73 | | |
74 | 410 | p += tag_len; |
75 | 410 | left = gdo_len - (p - gdo); |
76 | 410 | } |
77 | | |
78 | 61 | if (!iccsn_found && iccsn_len) |
79 | 45 | *iccsn_len = 0; |
80 | 61 | if (!chn_found && chn_len) |
81 | 0 | *chn_len = 0; |
82 | | |
83 | 61 | return r; |
84 | 61 | } |
85 | | |
86 | | |
87 | | |
88 | | int |
89 | | sc_parse_ef_gdo(struct sc_card *card, |
90 | | unsigned char *iccsn, size_t *iccsn_len, |
91 | | unsigned char *chn, size_t *chn_len) |
92 | 403 | { |
93 | 403 | struct sc_context *ctx; |
94 | 403 | struct sc_path path; |
95 | 403 | struct sc_file *file; |
96 | 403 | unsigned char *gdo = NULL; |
97 | 403 | size_t gdo_len = 0; |
98 | 403 | int r; |
99 | | |
100 | 403 | if (!card) |
101 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
102 | | |
103 | 403 | ctx = card->ctx; |
104 | | |
105 | 403 | LOG_FUNC_CALLED(ctx); |
106 | | |
107 | 403 | sc_format_path("3F002F02", &path); |
108 | 403 | r = sc_select_file(card, &path, &file); |
109 | 403 | LOG_TEST_GOTO_ERR(ctx, r, "Cannot select EF(GDO) file"); |
110 | | |
111 | 69 | if (file->size) { |
112 | 11 | gdo_len = file->size; |
113 | 58 | } else { |
114 | 58 | gdo_len = 64; |
115 | 58 | } |
116 | 69 | gdo = malloc(gdo_len); |
117 | 69 | if (!gdo) { |
118 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
119 | 0 | goto err; |
120 | 0 | } |
121 | | |
122 | 69 | r = sc_read_binary(card, 0, gdo, gdo_len, 0); |
123 | 69 | LOG_TEST_GOTO_ERR(ctx, r, "Cannot read EF(GDO) file"); |
124 | | |
125 | 61 | r = sc_parse_ef_gdo_content(gdo, r, iccsn, iccsn_len, chn, chn_len); |
126 | | |
127 | 403 | err: |
128 | 403 | sc_file_free(file); |
129 | 403 | free(gdo); |
130 | | |
131 | 403 | LOG_FUNC_RETURN(ctx, r); |
132 | 403 | } |