root / libcacard / vcard.c @ f141ccfa
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 | } |
204 | 111a38b0 | Robert Relyea | |
205 | 111a38b0 | Robert Relyea | void
|
206 | 111a38b0 | Robert Relyea | vcard_get_atr(VCard *vcard, unsigned char *atr, int *atr_len) |
207 | 111a38b0 | Robert Relyea | { |
208 | 111a38b0 | Robert Relyea | if (vcard->vcard_get_atr) {
|
209 | 111a38b0 | Robert Relyea | (*vcard->vcard_get_atr)(vcard, atr, atr_len); |
210 | 111a38b0 | Robert Relyea | return;
|
211 | 111a38b0 | Robert Relyea | } |
212 | 111a38b0 | Robert Relyea | vcard_emul_get_atr(vcard, atr, atr_len); |
213 | 111a38b0 | Robert Relyea | } |
214 | 111a38b0 | Robert Relyea | |
215 | 111a38b0 | Robert Relyea | void
|
216 | 111a38b0 | Robert Relyea | vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr) |
217 | 111a38b0 | Robert Relyea | { |
218 | 111a38b0 | Robert Relyea | card->vcard_get_atr = vcard_get_atr; |
219 | 111a38b0 | Robert Relyea | } |
220 | 111a38b0 | Robert Relyea | |
221 | 111a38b0 | Robert Relyea | |
222 | 111a38b0 | Robert Relyea | VCardStatus |
223 | 111a38b0 | Robert Relyea | vcard_add_applet(VCard *card, VCardApplet *applet) |
224 | 111a38b0 | Robert Relyea | { |
225 | 111a38b0 | Robert Relyea | applet->next = card->applet_list; |
226 | 111a38b0 | Robert Relyea | card->applet_list = applet; |
227 | 111a38b0 | Robert Relyea | /* if our card-type is direct, always call the applet */
|
228 | 111a38b0 | Robert Relyea | if (card->type == VCARD_DIRECT) {
|
229 | 111a38b0 | Robert Relyea | int i;
|
230 | 111a38b0 | Robert Relyea | |
231 | 111a38b0 | Robert Relyea | for (i = 0; i < MAX_CHANNEL; i++) { |
232 | 111a38b0 | Robert Relyea | card->current_applet[i] = applet; |
233 | 111a38b0 | Robert Relyea | } |
234 | 111a38b0 | Robert Relyea | } |
235 | 111a38b0 | Robert Relyea | return VCARD_DONE;
|
236 | 111a38b0 | Robert Relyea | } |
237 | 111a38b0 | Robert Relyea | |
238 | 111a38b0 | Robert Relyea | /*
|
239 | 111a38b0 | Robert Relyea | * manage applets
|
240 | 111a38b0 | Robert Relyea | */
|
241 | 111a38b0 | Robert Relyea | VCardApplet * |
242 | 111a38b0 | Robert Relyea | vcard_find_applet(VCard *card, unsigned char *aid, int aid_len) |
243 | 111a38b0 | Robert Relyea | { |
244 | 111a38b0 | Robert Relyea | VCardApplet *current_applet; |
245 | 111a38b0 | Robert Relyea | |
246 | 111a38b0 | Robert Relyea | for (current_applet = card->applet_list; current_applet;
|
247 | 111a38b0 | Robert Relyea | current_applet = current_applet->next) { |
248 | 111a38b0 | Robert Relyea | if (current_applet->aid_len != aid_len) {
|
249 | 111a38b0 | Robert Relyea | continue;
|
250 | 111a38b0 | Robert Relyea | } |
251 | 111a38b0 | Robert Relyea | if (memcmp(current_applet->aid, aid, aid_len) == 0) { |
252 | 111a38b0 | Robert Relyea | break;
|
253 | 111a38b0 | Robert Relyea | } |
254 | 111a38b0 | Robert Relyea | } |
255 | 111a38b0 | Robert Relyea | return current_applet;
|
256 | 111a38b0 | Robert Relyea | } |
257 | 111a38b0 | Robert Relyea | |
258 | 111a38b0 | Robert Relyea | unsigned char * |
259 | 111a38b0 | Robert Relyea | vcard_applet_get_aid(VCardApplet *applet, int *aid_len)
|
260 | 111a38b0 | Robert Relyea | { |
261 | 111a38b0 | Robert Relyea | if (applet == NULL) { |
262 | 111a38b0 | Robert Relyea | return NULL; |
263 | 111a38b0 | Robert Relyea | } |
264 | 111a38b0 | Robert Relyea | *aid_len = applet->aid_len; |
265 | 111a38b0 | Robert Relyea | return applet->aid;
|
266 | 111a38b0 | Robert Relyea | } |
267 | 111a38b0 | Robert Relyea | |
268 | 111a38b0 | Robert Relyea | |
269 | 111a38b0 | Robert Relyea | void
|
270 | 111a38b0 | Robert Relyea | vcard_select_applet(VCard *card, int channel, VCardApplet *applet)
|
271 | 111a38b0 | Robert Relyea | { |
272 | 111a38b0 | Robert Relyea | assert(channel < MAX_CHANNEL); |
273 | 111a38b0 | Robert Relyea | card->current_applet[channel] = applet; |
274 | 111a38b0 | Robert Relyea | /* reset the applet */
|
275 | 111a38b0 | Robert Relyea | if (applet && applet->reset_applet) {
|
276 | 111a38b0 | Robert Relyea | applet->reset_applet(card, channel); |
277 | 111a38b0 | Robert Relyea | } |
278 | 111a38b0 | Robert Relyea | } |
279 | 111a38b0 | Robert Relyea | |
280 | 111a38b0 | Robert Relyea | VCardAppletPrivate * |
281 | 111a38b0 | Robert Relyea | vcard_get_current_applet_private(VCard *card, int channel)
|
282 | 111a38b0 | Robert Relyea | { |
283 | 111a38b0 | Robert Relyea | VCardApplet *applet = card->current_applet[channel]; |
284 | 111a38b0 | Robert Relyea | |
285 | 111a38b0 | Robert Relyea | if (applet == NULL) { |
286 | 111a38b0 | Robert Relyea | return NULL; |
287 | 111a38b0 | Robert Relyea | } |
288 | 111a38b0 | Robert Relyea | return applet->applet_private;
|
289 | 111a38b0 | Robert Relyea | } |
290 | 111a38b0 | Robert Relyea | |
291 | 111a38b0 | Robert Relyea | VCardStatus |
292 | 111a38b0 | Robert Relyea | vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu, |
293 | 111a38b0 | Robert Relyea | VCardResponse **response) |
294 | 111a38b0 | Robert Relyea | { |
295 | 111a38b0 | Robert Relyea | if (card->current_applet[apdu->a_channel]) {
|
296 | 111a38b0 | Robert Relyea | return card->current_applet[apdu->a_channel]->process_apdu(
|
297 | 111a38b0 | Robert Relyea | card, apdu, response); |
298 | 111a38b0 | Robert Relyea | } |
299 | 111a38b0 | Robert Relyea | return VCARD_NEXT;
|
300 | 111a38b0 | Robert Relyea | } |
301 | 111a38b0 | Robert Relyea | |
302 | 111a38b0 | Robert Relyea | /*
|
303 | 111a38b0 | Robert Relyea | * Accessor functions
|
304 | 111a38b0 | Robert Relyea | */
|
305 | 111a38b0 | Robert Relyea | /* accessor functions for the response buffer */
|
306 | 111a38b0 | Robert Relyea | VCardBufferResponse * |
307 | 111a38b0 | Robert Relyea | vcard_get_buffer_response(VCard *card) |
308 | 111a38b0 | Robert Relyea | { |
309 | 111a38b0 | Robert Relyea | return card->vcard_buffer_response;
|
310 | 111a38b0 | Robert Relyea | } |
311 | 111a38b0 | Robert Relyea | |
312 | 111a38b0 | Robert Relyea | void
|
313 | 111a38b0 | Robert Relyea | vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer) |
314 | 111a38b0 | Robert Relyea | { |
315 | 111a38b0 | Robert Relyea | card->vcard_buffer_response = buffer; |
316 | 111a38b0 | Robert Relyea | } |
317 | 111a38b0 | Robert Relyea | |
318 | 111a38b0 | Robert Relyea | |
319 | 111a38b0 | Robert Relyea | /* accessor functions for the type */
|
320 | 111a38b0 | Robert Relyea | VCardType |
321 | 111a38b0 | Robert Relyea | vcard_get_type(VCard *card) |
322 | 111a38b0 | Robert Relyea | { |
323 | 111a38b0 | Robert Relyea | return card->type;
|
324 | 111a38b0 | Robert Relyea | } |
325 | 111a38b0 | Robert Relyea | |
326 | 111a38b0 | Robert Relyea | void
|
327 | 111a38b0 | Robert Relyea | vcard_set_type(VCard *card, VCardType type) |
328 | 111a38b0 | Robert Relyea | { |
329 | 111a38b0 | Robert Relyea | card->type = type; |
330 | 111a38b0 | Robert Relyea | } |
331 | 111a38b0 | Robert Relyea | |
332 | 111a38b0 | Robert Relyea | /* accessor for private data */
|
333 | 111a38b0 | Robert Relyea | VCardEmul * |
334 | 111a38b0 | Robert Relyea | vcard_get_private(VCard *vcard) |
335 | 111a38b0 | Robert Relyea | { |
336 | 111a38b0 | Robert Relyea | return vcard->vcard_private;
|
337 | 111a38b0 | Robert Relyea | } |