root / libcacard / vcard.c @ 92f562ec
History | View | Annotate | Download (7.8 kB)
1 | 111a38b0 | Robert Relyea | /*
|
---|---|---|---|
2 | 111a38b0 | Robert Relyea | * implement the Java card standard.
|
3 | 111a38b0 | Robert Relyea | *
|
4 | 111a38b0 | Robert Relyea | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
5 | 111a38b0 | Robert Relyea | * See the COPYING.LIB file in the top-level directory.
|
6 | 111a38b0 | Robert Relyea | */
|
7 | 111a38b0 | Robert Relyea | |
8 | 111a38b0 | Robert Relyea | #include "qemu-common.h" |
9 | 111a38b0 | Robert Relyea | |
10 | 111a38b0 | Robert Relyea | #include "vcard.h" |
11 | 111a38b0 | Robert Relyea | #include "vcard_emul.h" |
12 | 111a38b0 | Robert Relyea | #include "card_7816t.h" |
13 | 111a38b0 | Robert Relyea | |
14 | 111a38b0 | Robert Relyea | struct VCardAppletStruct {
|
15 | 111a38b0 | Robert Relyea | VCardApplet *next; |
16 | 111a38b0 | Robert Relyea | VCardProcessAPDU process_apdu; |
17 | 111a38b0 | Robert Relyea | VCardResetApplet reset_applet; |
18 | 111a38b0 | Robert Relyea | unsigned char *aid; |
19 | 111a38b0 | Robert Relyea | int aid_len;
|
20 | 111a38b0 | Robert Relyea | void *applet_private;
|
21 | 111a38b0 | Robert Relyea | VCardAppletPrivateFree applet_private_free; |
22 | 111a38b0 | Robert Relyea | }; |
23 | 111a38b0 | Robert Relyea | |
24 | 111a38b0 | Robert Relyea | struct VCardStruct {
|
25 | 111a38b0 | Robert Relyea | int reference_count;
|
26 | 111a38b0 | Robert Relyea | VCardApplet *applet_list; |
27 | 111a38b0 | Robert Relyea | VCardApplet *current_applet[MAX_CHANNEL]; |
28 | 111a38b0 | Robert Relyea | VCardBufferResponse *vcard_buffer_response; |
29 | 111a38b0 | Robert Relyea | VCardType type; |
30 | 111a38b0 | Robert Relyea | VCardEmul *vcard_private; |
31 | 111a38b0 | Robert Relyea | VCardEmulFree vcard_private_free; |
32 | 111a38b0 | Robert Relyea | VCardGetAtr vcard_get_atr; |
33 | 111a38b0 | Robert Relyea | }; |
34 | 111a38b0 | Robert Relyea | |
35 | 111a38b0 | Robert Relyea | VCardBufferResponse * |
36 | 111a38b0 | Robert Relyea | vcard_buffer_response_new(unsigned char *buffer, int size) |
37 | 111a38b0 | Robert Relyea | { |
38 | 111a38b0 | Robert Relyea | VCardBufferResponse *new_buffer; |
39 | 111a38b0 | Robert Relyea | |
40 | 7267c094 | Anthony Liguori | new_buffer = (VCardBufferResponse *)g_malloc(sizeof(VCardBufferResponse));
|
41 | 7267c094 | Anthony Liguori | new_buffer->buffer = (unsigned char *)g_malloc(size); |
42 | 111a38b0 | Robert Relyea | memcpy(new_buffer->buffer, buffer, size); |
43 | 111a38b0 | Robert Relyea | new_buffer->buffer_len = size; |
44 | 111a38b0 | Robert Relyea | new_buffer->current = new_buffer->buffer; |
45 | 111a38b0 | Robert Relyea | new_buffer->len = size; |
46 | 111a38b0 | Robert Relyea | return new_buffer;
|
47 | 111a38b0 | Robert Relyea | } |
48 | 111a38b0 | Robert Relyea | |
49 | 111a38b0 | Robert Relyea | void
|
50 | 111a38b0 | Robert Relyea | vcard_buffer_response_delete(VCardBufferResponse *buffer_response) |
51 | 111a38b0 | Robert Relyea | { |
52 | 111a38b0 | Robert Relyea | if (buffer_response == NULL) { |
53 | 111a38b0 | Robert Relyea | return;
|
54 | 111a38b0 | Robert Relyea | } |
55 | 111a38b0 | Robert Relyea | if (buffer_response->buffer) {
|
56 | 7267c094 | Anthony Liguori | g_free(buffer_response->buffer); |
57 | 111a38b0 | Robert Relyea | } |
58 | 7267c094 | Anthony Liguori | g_free(buffer_response); |
59 | 111a38b0 | Robert Relyea | } |
60 | 111a38b0 | Robert Relyea | |
61 | 111a38b0 | Robert Relyea | |
62 | 111a38b0 | Robert Relyea | /*
|
63 | 111a38b0 | Robert Relyea | * clean up state after a reset
|
64 | 111a38b0 | Robert Relyea | */
|
65 | 111a38b0 | Robert Relyea | void
|
66 | 111a38b0 | Robert Relyea | vcard_reset(VCard *card, VCardPower power) |
67 | 111a38b0 | Robert Relyea | { |
68 | 111a38b0 | Robert Relyea | int i;
|
69 | 111a38b0 | Robert Relyea | VCardApplet *applet = NULL;
|
70 | 111a38b0 | Robert Relyea | |
71 | 111a38b0 | Robert Relyea | if (card->type == VCARD_DIRECT) {
|
72 | 111a38b0 | Robert Relyea | /* select the last applet */
|
73 | 111a38b0 | Robert Relyea | VCardApplet *current_applet = NULL;
|
74 | 111a38b0 | Robert Relyea | for (current_applet = card->applet_list; current_applet;
|
75 | 111a38b0 | Robert Relyea | current_applet = current_applet->next) { |
76 | 111a38b0 | Robert Relyea | applet = current_applet; |
77 | 111a38b0 | Robert Relyea | } |
78 | 111a38b0 | Robert Relyea | } |
79 | 111a38b0 | Robert Relyea | for (i = 0; i < MAX_CHANNEL; i++) { |
80 | 111a38b0 | Robert Relyea | card->current_applet[i] = applet; |
81 | 111a38b0 | Robert Relyea | } |
82 | 111a38b0 | Robert Relyea | if (card->vcard_buffer_response) {
|
83 | 111a38b0 | Robert Relyea | vcard_buffer_response_delete(card->vcard_buffer_response); |
84 | 111a38b0 | Robert Relyea | card->vcard_buffer_response = NULL;
|
85 | 111a38b0 | Robert Relyea | } |
86 | 111a38b0 | Robert Relyea | vcard_emul_reset(card, power); |
87 | 111a38b0 | Robert Relyea | if (applet) {
|
88 | 111a38b0 | Robert Relyea | applet->reset_applet(card, 0);
|
89 | 111a38b0 | Robert Relyea | } |
90 | 111a38b0 | Robert Relyea | } |
91 | 111a38b0 | Robert Relyea | |
92 | 111a38b0 | Robert Relyea | /* applet utilities */
|
93 | 111a38b0 | Robert Relyea | |
94 | 111a38b0 | Robert Relyea | /*
|
95 | 111a38b0 | Robert Relyea | * applet utilities
|
96 | 111a38b0 | Robert Relyea | */
|
97 | 111a38b0 | Robert Relyea | /* constructor */
|
98 | 111a38b0 | Robert Relyea | VCardApplet * |
99 | 111a38b0 | Robert Relyea | vcard_new_applet(VCardProcessAPDU applet_process_function, |
100 | 111a38b0 | Robert Relyea | VCardResetApplet applet_reset_function, |
101 | 111a38b0 | Robert Relyea | unsigned char *aid, int aid_len) |
102 | 111a38b0 | Robert Relyea | { |
103 | 111a38b0 | Robert Relyea | VCardApplet *applet; |
104 | 111a38b0 | Robert Relyea | |
105 | 7267c094 | Anthony Liguori | applet = (VCardApplet *)g_malloc(sizeof(VCardApplet));
|
106 | 111a38b0 | Robert Relyea | applet->next = NULL;
|
107 | 111a38b0 | Robert Relyea | applet->applet_private = NULL;
|
108 | 111a38b0 | Robert Relyea | applet->applet_private_free = NULL;
|
109 | 111a38b0 | Robert Relyea | applet->process_apdu = applet_process_function; |
110 | 111a38b0 | Robert Relyea | applet->reset_applet = applet_reset_function; |
111 | 111a38b0 | Robert Relyea | |
112 | 7267c094 | Anthony Liguori | applet->aid = g_malloc(aid_len); |
113 | 111a38b0 | Robert Relyea | memcpy(applet->aid, aid, aid_len); |
114 | 111a38b0 | Robert Relyea | applet->aid_len = aid_len; |
115 | 111a38b0 | Robert Relyea | return applet;
|
116 | 111a38b0 | Robert Relyea | } |
117 | 111a38b0 | Robert Relyea | |
118 | 111a38b0 | Robert Relyea | /* destructor */
|
119 | 111a38b0 | Robert Relyea | void
|
120 | 111a38b0 | Robert Relyea | vcard_delete_applet(VCardApplet *applet) |
121 | 111a38b0 | Robert Relyea | { |
122 | 111a38b0 | Robert Relyea | if (applet == NULL) { |
123 | 111a38b0 | Robert Relyea | return;
|
124 | 111a38b0 | Robert Relyea | } |
125 | 111a38b0 | Robert Relyea | if (applet->applet_private_free) {
|
126 | 111a38b0 | Robert Relyea | applet->applet_private_free(applet->applet_private); |
127 | 111a38b0 | Robert Relyea | applet->applet_private = NULL;
|
128 | 111a38b0 | Robert Relyea | } |
129 | 111a38b0 | Robert Relyea | if (applet->aid) {
|
130 | 7267c094 | Anthony Liguori | g_free(applet->aid); |
131 | 111a38b0 | Robert Relyea | applet->aid = NULL;
|
132 | 111a38b0 | Robert Relyea | } |
133 | 7267c094 | Anthony Liguori | g_free(applet); |
134 | 111a38b0 | Robert Relyea | } |
135 | 111a38b0 | Robert Relyea | |
136 | 111a38b0 | Robert Relyea | /* accessor */
|
137 | 111a38b0 | Robert Relyea | void
|
138 | 111a38b0 | Robert Relyea | vcard_set_applet_private(VCardApplet *applet, VCardAppletPrivate *private, |
139 | 111a38b0 | Robert Relyea | VCardAppletPrivateFree private_free) |
140 | 111a38b0 | Robert Relyea | { |
141 | 111a38b0 | Robert Relyea | if (applet->applet_private_free) {
|
142 | 111a38b0 | Robert Relyea | applet->applet_private_free(applet->applet_private); |
143 | 111a38b0 | Robert Relyea | } |
144 | 111a38b0 | Robert Relyea | applet->applet_private = private; |
145 | 111a38b0 | Robert Relyea | applet->applet_private_free = private_free; |
146 | 111a38b0 | Robert Relyea | } |
147 | 111a38b0 | Robert Relyea | |
148 | 111a38b0 | Robert Relyea | VCard * |
149 | 111a38b0 | Robert Relyea | vcard_new(VCardEmul *private, VCardEmulFree private_free) |
150 | 111a38b0 | Robert Relyea | { |
151 | 111a38b0 | Robert Relyea | VCard *new_card; |
152 | 111a38b0 | Robert Relyea | int i;
|
153 | 111a38b0 | Robert Relyea | |
154 | 7267c094 | Anthony Liguori | new_card = (VCard *)g_malloc(sizeof(VCard));
|
155 | 111a38b0 | Robert Relyea | new_card->applet_list = NULL;
|
156 | 111a38b0 | Robert Relyea | for (i = 0; i < MAX_CHANNEL; i++) { |
157 | 111a38b0 | Robert Relyea | new_card->current_applet[i] = NULL;
|
158 | 111a38b0 | Robert Relyea | } |
159 | 111a38b0 | Robert Relyea | new_card->vcard_buffer_response = NULL;
|
160 | 111a38b0 | Robert Relyea | new_card->type = VCARD_VM; |
161 | 111a38b0 | Robert Relyea | new_card->vcard_private = private; |
162 | 111a38b0 | Robert Relyea | new_card->vcard_private_free = private_free; |
163 | 111a38b0 | Robert Relyea | new_card->vcard_get_atr = NULL;
|
164 | 111a38b0 | Robert Relyea | new_card->reference_count = 1;
|
165 | 111a38b0 | Robert Relyea | return new_card;
|
166 | 111a38b0 | Robert Relyea | } |
167 | 111a38b0 | Robert Relyea | |
168 | 111a38b0 | Robert Relyea | VCard * |
169 | 111a38b0 | Robert Relyea | vcard_reference(VCard *vcard) |
170 | 111a38b0 | Robert Relyea | { |
171 | 111a38b0 | Robert Relyea | if (vcard == NULL) { |
172 | 111a38b0 | Robert Relyea | return NULL; |
173 | 111a38b0 | Robert Relyea | } |
174 | 111a38b0 | Robert Relyea | vcard->reference_count++; |
175 | 111a38b0 | Robert Relyea | return vcard;
|
176 | 111a38b0 | Robert Relyea | } |
177 | 111a38b0 | Robert Relyea | |
178 | 111a38b0 | Robert Relyea | void
|
179 | 111a38b0 | Robert Relyea | vcard_free(VCard *vcard) |
180 | 111a38b0 | Robert Relyea | { |
181 | 111a38b0 | Robert Relyea | VCardApplet *current_applet = NULL;
|
182 | 111a38b0 | Robert Relyea | VCardApplet *next_applet = NULL;
|
183 | 111a38b0 | Robert Relyea | |
184 | 111a38b0 | Robert Relyea | if (vcard == NULL) { |
185 | 111a38b0 | Robert Relyea | return;
|
186 | 111a38b0 | Robert Relyea | } |
187 | 111a38b0 | Robert Relyea | vcard->reference_count--; |
188 | 111a38b0 | Robert Relyea | if (vcard->reference_count != 0) { |
189 | 111a38b0 | Robert Relyea | return;
|
190 | 111a38b0 | Robert Relyea | } |
191 | 111a38b0 | Robert Relyea | if (vcard->vcard_private_free) {
|
192 | 111a38b0 | Robert Relyea | (*vcard->vcard_private_free)(vcard->vcard_private); |
193 | 111a38b0 | Robert Relyea | vcard->vcard_private_free = 0;
|
194 | 111a38b0 | Robert Relyea | vcard->vcard_private = 0;
|
195 | 111a38b0 | Robert Relyea | } |
196 | 111a38b0 | Robert Relyea | for (current_applet = vcard->applet_list; current_applet;
|
197 | 111a38b0 | Robert Relyea | current_applet = next_applet) { |
198 | 111a38b0 | Robert Relyea | next_applet = current_applet->next; |
199 | 111a38b0 | Robert Relyea | vcard_delete_applet(current_applet); |
200 | 111a38b0 | Robert Relyea | } |
201 | 111a38b0 | Robert Relyea | vcard_buffer_response_delete(vcard->vcard_buffer_response); |
202 | 7267c094 | Anthony Liguori | g_free(vcard); |
203 | 111a38b0 | Robert Relyea | return;
|
204 | 111a38b0 | Robert Relyea | } |
205 | 111a38b0 | Robert Relyea | |
206 | 111a38b0 | Robert Relyea | void
|
207 | 111a38b0 | Robert Relyea | vcard_get_atr(VCard *vcard, unsigned char *atr, int *atr_len) |
208 | 111a38b0 | Robert Relyea | { |
209 | 111a38b0 | Robert Relyea | if (vcard->vcard_get_atr) {
|
210 | 111a38b0 | Robert Relyea | (*vcard->vcard_get_atr)(vcard, atr, atr_len); |
211 | 111a38b0 | Robert Relyea | return;
|
212 | 111a38b0 | Robert Relyea | } |
213 | 111a38b0 | Robert Relyea | vcard_emul_get_atr(vcard, atr, atr_len); |
214 | 111a38b0 | Robert Relyea | } |
215 | 111a38b0 | Robert Relyea | |
216 | 111a38b0 | Robert Relyea | void
|
217 | 111a38b0 | Robert Relyea | vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr) |
218 | 111a38b0 | Robert Relyea | { |
219 | 111a38b0 | Robert Relyea | card->vcard_get_atr = vcard_get_atr; |
220 | 111a38b0 | Robert Relyea | } |
221 | 111a38b0 | Robert Relyea | |
222 | 111a38b0 | Robert Relyea | |
223 | 111a38b0 | Robert Relyea | VCardStatus |
224 | 111a38b0 | Robert Relyea | vcard_add_applet(VCard *card, VCardApplet *applet) |
225 | 111a38b0 | Robert Relyea | { |
226 | 111a38b0 | Robert Relyea | applet->next = card->applet_list; |
227 | 111a38b0 | Robert Relyea | card->applet_list = applet; |
228 | 111a38b0 | Robert Relyea | /* if our card-type is direct, always call the applet */
|
229 | 111a38b0 | Robert Relyea | if (card->type == VCARD_DIRECT) {
|
230 | 111a38b0 | Robert Relyea | int i;
|
231 | 111a38b0 | Robert Relyea | |
232 | 111a38b0 | Robert Relyea | for (i = 0; i < MAX_CHANNEL; i++) { |
233 | 111a38b0 | Robert Relyea | card->current_applet[i] = applet; |
234 | 111a38b0 | Robert Relyea | } |
235 | 111a38b0 | Robert Relyea | } |
236 | 111a38b0 | Robert Relyea | return VCARD_DONE;
|
237 | 111a38b0 | Robert Relyea | } |
238 | 111a38b0 | Robert Relyea | |
239 | 111a38b0 | Robert Relyea | /*
|
240 | 111a38b0 | Robert Relyea | * manage applets
|
241 | 111a38b0 | Robert Relyea | */
|
242 | 111a38b0 | Robert Relyea | VCardApplet * |
243 | 111a38b0 | Robert Relyea | vcard_find_applet(VCard *card, unsigned char *aid, int aid_len) |
244 | 111a38b0 | Robert Relyea | { |
245 | 111a38b0 | Robert Relyea | VCardApplet *current_applet; |
246 | 111a38b0 | Robert Relyea | |
247 | 111a38b0 | Robert Relyea | for (current_applet = card->applet_list; current_applet;
|
248 | 111a38b0 | Robert Relyea | current_applet = current_applet->next) { |
249 | 111a38b0 | Robert Relyea | if (current_applet->aid_len != aid_len) {
|
250 | 111a38b0 | Robert Relyea | continue;
|
251 | 111a38b0 | Robert Relyea | } |
252 | 111a38b0 | Robert Relyea | if (memcmp(current_applet->aid, aid, aid_len) == 0) { |
253 | 111a38b0 | Robert Relyea | break;
|
254 | 111a38b0 | Robert Relyea | } |
255 | 111a38b0 | Robert Relyea | } |
256 | 111a38b0 | Robert Relyea | return current_applet;
|
257 | 111a38b0 | Robert Relyea | } |
258 | 111a38b0 | Robert Relyea | |
259 | 111a38b0 | Robert Relyea | unsigned char * |
260 | 111a38b0 | Robert Relyea | vcard_applet_get_aid(VCardApplet *applet, int *aid_len)
|
261 | 111a38b0 | Robert Relyea | { |
262 | 111a38b0 | Robert Relyea | if (applet == NULL) { |
263 | 111a38b0 | Robert Relyea | return NULL; |
264 | 111a38b0 | Robert Relyea | } |
265 | 111a38b0 | Robert Relyea | *aid_len = applet->aid_len; |
266 | 111a38b0 | Robert Relyea | return applet->aid;
|
267 | 111a38b0 | Robert Relyea | } |
268 | 111a38b0 | Robert Relyea | |
269 | 111a38b0 | Robert Relyea | |
270 | 111a38b0 | Robert Relyea | void
|
271 | 111a38b0 | Robert Relyea | vcard_select_applet(VCard *card, int channel, VCardApplet *applet)
|
272 | 111a38b0 | Robert Relyea | { |
273 | 111a38b0 | Robert Relyea | assert(channel < MAX_CHANNEL); |
274 | 111a38b0 | Robert Relyea | card->current_applet[channel] = applet; |
275 | 111a38b0 | Robert Relyea | /* reset the applet */
|
276 | 111a38b0 | Robert Relyea | if (applet && applet->reset_applet) {
|
277 | 111a38b0 | Robert Relyea | applet->reset_applet(card, channel); |
278 | 111a38b0 | Robert Relyea | } |
279 | 111a38b0 | Robert Relyea | } |
280 | 111a38b0 | Robert Relyea | |
281 | 111a38b0 | Robert Relyea | VCardAppletPrivate * |
282 | 111a38b0 | Robert Relyea | vcard_get_current_applet_private(VCard *card, int channel)
|
283 | 111a38b0 | Robert Relyea | { |
284 | 111a38b0 | Robert Relyea | VCardApplet *applet = card->current_applet[channel]; |
285 | 111a38b0 | Robert Relyea | |
286 | 111a38b0 | Robert Relyea | if (applet == NULL) { |
287 | 111a38b0 | Robert Relyea | return NULL; |
288 | 111a38b0 | Robert Relyea | } |
289 | 111a38b0 | Robert Relyea | return applet->applet_private;
|
290 | 111a38b0 | Robert Relyea | } |
291 | 111a38b0 | Robert Relyea | |
292 | 111a38b0 | Robert Relyea | VCardStatus |
293 | 111a38b0 | Robert Relyea | vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu, |
294 | 111a38b0 | Robert Relyea | VCardResponse **response) |
295 | 111a38b0 | Robert Relyea | { |
296 | 111a38b0 | Robert Relyea | if (card->current_applet[apdu->a_channel]) {
|
297 | 111a38b0 | Robert Relyea | return card->current_applet[apdu->a_channel]->process_apdu(
|
298 | 111a38b0 | Robert Relyea | card, apdu, response); |
299 | 111a38b0 | Robert Relyea | } |
300 | 111a38b0 | Robert Relyea | return VCARD_NEXT;
|
301 | 111a38b0 | Robert Relyea | } |
302 | 111a38b0 | Robert Relyea | |
303 | 111a38b0 | Robert Relyea | /*
|
304 | 111a38b0 | Robert Relyea | * Accessor functions
|
305 | 111a38b0 | Robert Relyea | */
|
306 | 111a38b0 | Robert Relyea | /* accessor functions for the response buffer */
|
307 | 111a38b0 | Robert Relyea | VCardBufferResponse * |
308 | 111a38b0 | Robert Relyea | vcard_get_buffer_response(VCard *card) |
309 | 111a38b0 | Robert Relyea | { |
310 | 111a38b0 | Robert Relyea | return card->vcard_buffer_response;
|
311 | 111a38b0 | Robert Relyea | } |
312 | 111a38b0 | Robert Relyea | |
313 | 111a38b0 | Robert Relyea | void
|
314 | 111a38b0 | Robert Relyea | vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer) |
315 | 111a38b0 | Robert Relyea | { |
316 | 111a38b0 | Robert Relyea | card->vcard_buffer_response = buffer; |
317 | 111a38b0 | Robert Relyea | } |
318 | 111a38b0 | Robert Relyea | |
319 | 111a38b0 | Robert Relyea | |
320 | 111a38b0 | Robert Relyea | /* accessor functions for the type */
|
321 | 111a38b0 | Robert Relyea | VCardType |
322 | 111a38b0 | Robert Relyea | vcard_get_type(VCard *card) |
323 | 111a38b0 | Robert Relyea | { |
324 | 111a38b0 | Robert Relyea | return card->type;
|
325 | 111a38b0 | Robert Relyea | } |
326 | 111a38b0 | Robert Relyea | |
327 | 111a38b0 | Robert Relyea | void
|
328 | 111a38b0 | Robert Relyea | vcard_set_type(VCard *card, VCardType type) |
329 | 111a38b0 | Robert Relyea | { |
330 | 111a38b0 | Robert Relyea | card->type = type; |
331 | 111a38b0 | Robert Relyea | } |
332 | 111a38b0 | Robert Relyea | |
333 | 111a38b0 | Robert Relyea | /* accessor for private data */
|
334 | 111a38b0 | Robert Relyea | VCardEmul * |
335 | 111a38b0 | Robert Relyea | vcard_get_private(VCard *vcard) |
336 | 111a38b0 | Robert Relyea | { |
337 | 111a38b0 | Robert Relyea | return vcard->vcard_private;
|
338 | 111a38b0 | Robert Relyea | } |