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