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