/src/opensc/src/libopensc/ef-gdo.c
Line | Count | Source |
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 | 1.91k | { |
34 | 1.91k | int r = SC_SUCCESS, iccsn_found = 0, chn_found = 0; |
35 | 1.91k | const unsigned char *p = gdo; |
36 | 1.91k | size_t left = gdo_len; |
37 | | |
38 | 5.70k | while (left >= 2) { |
39 | 4.04k | unsigned int cla, tag; |
40 | 4.04k | size_t tag_len; |
41 | | |
42 | 4.04k | r = sc_asn1_read_tag(&p, left, &cla, &tag, &tag_len); |
43 | 4.04k | if (r != SC_SUCCESS) { |
44 | 138 | if (r == SC_ERROR_ASN1_END_OF_CONTENTS) { |
45 | | /* not enough data */ |
46 | 84 | r = SC_SUCCESS; |
47 | 84 | } |
48 | 138 | break; |
49 | 138 | } |
50 | 3.90k | if (p == NULL) { |
51 | | /* done parsing */ |
52 | 119 | break; |
53 | 119 | } |
54 | | |
55 | 3.78k | if (cla == SC_ASN1_TAG_APPLICATION) { |
56 | 2.15k | switch (tag) { |
57 | 1.13k | case 0x1A: |
58 | 1.13k | iccsn_found = 1; |
59 | 1.13k | if (iccsn && iccsn_len) { |
60 | 1.13k | memcpy(iccsn, p, MIN(tag_len, *iccsn_len)); |
61 | 1.13k | *iccsn_len = MIN(tag_len, *iccsn_len); |
62 | 1.13k | } |
63 | 1.13k | break; |
64 | 213 | case 0x1F20: |
65 | 213 | chn_found = 1; |
66 | 213 | 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 | 213 | break; |
71 | 2.15k | } |
72 | 2.15k | } |
73 | | |
74 | 3.78k | p += tag_len; |
75 | 3.78k | left = gdo_len - (p - gdo); |
76 | 3.78k | } |
77 | | |
78 | 1.91k | if (!iccsn_found && iccsn_len) |
79 | 1.75k | *iccsn_len = 0; |
80 | 1.91k | if (!chn_found && chn_len) |
81 | 0 | *chn_len = 0; |
82 | | |
83 | 1.91k | return r; |
84 | 1.91k | } |
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 | 4.84k | { |
93 | 4.84k | struct sc_context *ctx; |
94 | 4.84k | struct sc_path path; |
95 | 4.84k | struct sc_file *file; |
96 | 4.84k | unsigned char *gdo = NULL; |
97 | 4.84k | size_t gdo_len = 0; |
98 | 4.84k | int r; |
99 | | |
100 | 4.84k | if (!card) |
101 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
102 | | |
103 | 4.84k | ctx = card->ctx; |
104 | | |
105 | 4.84k | LOG_FUNC_CALLED(ctx); |
106 | | |
107 | 4.84k | sc_format_path("3F002F02", &path); |
108 | 4.84k | r = sc_select_file(card, &path, &file); |
109 | 4.84k | LOG_TEST_GOTO_ERR(ctx, r, "Cannot select EF(GDO) file"); |
110 | | |
111 | 1.99k | if (file->size) { |
112 | 123 | gdo_len = file->size; |
113 | 1.87k | } else { |
114 | 1.87k | gdo_len = 64; |
115 | 1.87k | } |
116 | 1.99k | gdo = malloc(gdo_len); |
117 | 1.99k | if (!gdo) { |
118 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
119 | 0 | goto err; |
120 | 0 | } |
121 | | |
122 | 1.99k | r = sc_read_binary(card, 0, gdo, gdo_len, 0); |
123 | 1.99k | LOG_TEST_GOTO_ERR(ctx, r, "Cannot read EF(GDO) file"); |
124 | | |
125 | 1.91k | r = sc_parse_ef_gdo_content(gdo, r, iccsn, iccsn_len, chn, chn_len); |
126 | | |
127 | 4.84k | err: |
128 | 4.84k | sc_file_free(file); |
129 | 4.84k | free(gdo); |
130 | | |
131 | 4.84k | LOG_FUNC_RETURN(ctx, r); |
132 | 4.84k | } |