/src/opensc/src/pkcs11/slot.c
Line | Count | Source |
1 | | /* |
2 | | * slot.c: reader, smart card and slot related management functions |
3 | | * |
4 | | * Copyright (C) 2002 Timo Teräs <timo.teras@iki.fi> |
5 | | * Copyright (C) 2009 Martin Paljak <martin@martinpaljak.net> |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it under the terms of the GNU Lesser General Public |
9 | | * License as published by the Free Software Foundation; either |
10 | | * version 2.1 of the License, or (at your option) any later version. |
11 | | * |
12 | | * This library is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | | * Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this library; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | | */ |
21 | | |
22 | | #include "config.h" |
23 | | #include "libopensc/opensc.h" |
24 | | |
25 | | #include <string.h> |
26 | | #include <stdlib.h> |
27 | | |
28 | | #include "sc-pkcs11.h" |
29 | | |
30 | | /* Print virtual_slots list. Called by DEBUG_VSS(S, C) */ |
31 | | void _debug_virtual_slots(sc_pkcs11_slot_t *p) |
32 | 15.4k | { |
33 | 15.4k | int i, vs_size; |
34 | 15.4k | sc_pkcs11_slot_t * slot; |
35 | | |
36 | 15.4k | vs_size = list_size(&virtual_slots); |
37 | 15.4k | _sc_debug(context, 10, |
38 | 15.4k | "VSS size:%d", vs_size); |
39 | 15.4k | _sc_debug(context, 10, |
40 | 15.4k | "VSS [i] id flags LU events nsessions slot_info.flags reader p11card description"); |
41 | 30.8k | for (i = 0; i < vs_size; i++) { |
42 | 15.4k | slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
43 | 15.4k | if (slot) { |
44 | 15.4k | _sc_debug(context, 10, |
45 | 15.4k | "VSS %s[%d] 0x%2.2lx 0x%4.4x %d %d %d %4.4lx %p %p %.64s", |
46 | 15.4k | ((slot == p) ? "*" : " "), |
47 | 15.4k | i, slot->id, slot->flags, slot->login_user, slot->events, slot->nsessions, |
48 | 15.4k | slot->slot_info.flags, |
49 | 15.4k | slot->reader, slot->p11card, |
50 | 15.4k | slot->slot_info.slotDescription); |
51 | 15.4k | } |
52 | 15.4k | } |
53 | 15.4k | _sc_debug(context, 10, "VSS END"); |
54 | 15.4k | } |
55 | | |
56 | | static struct sc_pkcs11_framework_ops *frameworks[] = { |
57 | | &framework_pkcs15, |
58 | | #ifdef USE_PKCS15_INIT |
59 | | /* This should be the last framework, because it |
60 | | * will assume the card is blank and try to initialize it */ |
61 | | &framework_pkcs15init, |
62 | | #endif |
63 | | NULL |
64 | | }; |
65 | | |
66 | | static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader) |
67 | 15.4k | { |
68 | 15.4k | unsigned int i; |
69 | 15.4k | CK_UTF8CHAR slotDescription[64]; |
70 | 15.4k | CK_UTF8CHAR manufacturerID[32]; |
71 | | |
72 | 15.4k | if (reader == NULL) |
73 | 0 | return NULL; |
74 | 15.4k | strcpy_bp(slotDescription, reader->name, 64); |
75 | 15.4k | strcpy_bp(manufacturerID, reader->vendor, 32); |
76 | | |
77 | | /* Locate a slot related to the reader */ |
78 | 15.4k | for (i = 0; i<list_size(&virtual_slots); i++) { |
79 | 0 | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
80 | 0 | if (slot->reader == NULL |
81 | 0 | && 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64) |
82 | 0 | && 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32) |
83 | 0 | && slot->slot_info.hardwareVersion.major == reader->version_major |
84 | 0 | && slot->slot_info.hardwareVersion.minor == reader->version_minor) { |
85 | 0 | return slot; |
86 | 0 | } |
87 | 0 | } |
88 | 15.4k | return NULL; |
89 | 15.4k | } |
90 | | |
91 | | void init_slot_info(CK_SLOT_INFO_PTR pInfo, sc_reader_t *reader) |
92 | 27.7k | { |
93 | 27.7k | if (reader) { |
94 | 27.7k | strcpy_bp(pInfo->slotDescription, reader->name, 64); |
95 | 27.7k | strcpy_bp(pInfo->manufacturerID, reader->vendor, 32); |
96 | 27.7k | pInfo->hardwareVersion.major = reader->version_major; |
97 | 27.7k | pInfo->hardwareVersion.minor = reader->version_minor; |
98 | 27.7k | } else { |
99 | 0 | strcpy_bp(pInfo->slotDescription, "Virtual hotplug slot", 64); |
100 | 0 | strcpy_bp(pInfo->manufacturerID, OPENSC_VS_FF_COMPANY_NAME, 32); |
101 | 0 | pInfo->hardwareVersion.major = OPENSC_VERSION_MAJOR; |
102 | 0 | pInfo->hardwareVersion.minor = OPENSC_VERSION_MINOR; |
103 | 0 | } |
104 | 27.7k | pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT; |
105 | 27.7k | pInfo->firmwareVersion.major = 0; |
106 | 27.7k | pInfo->firmwareVersion.minor = 0; |
107 | 27.7k | } |
108 | | |
109 | | /* simclist helpers to locate interesting objects by ID */ |
110 | | static int object_list_seeker(const void *el, const void *key) |
111 | 1.44k | { |
112 | 1.44k | const struct sc_pkcs11_object *object = (struct sc_pkcs11_object *)el; |
113 | | |
114 | 1.44k | if ((el == NULL) || (key == NULL)) |
115 | 0 | return 0; |
116 | 1.44k | if (object->handle == *(CK_OBJECT_HANDLE*)key) |
117 | 627 | return 1; |
118 | 813 | return 0; |
119 | 1.44k | } |
120 | | |
121 | | CK_RV create_slot(sc_reader_t *reader) |
122 | 15.4k | { |
123 | | /* find unused slots previously allocated for the same reader */ |
124 | 15.4k | struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader); |
125 | | |
126 | | /* create a new slot if no empty slot is available */ |
127 | 15.4k | if (!slot) { |
128 | 15.4k | sc_log(context, "Creating new slot"); |
129 | 15.4k | if (list_size(&virtual_slots) >= sc_pkcs11_conf.max_virtual_slots) |
130 | 0 | return CKR_FUNCTION_FAILED; |
131 | | |
132 | 15.4k | slot = (struct sc_pkcs11_slot *)calloc(1, sizeof(struct sc_pkcs11_slot)); |
133 | 15.4k | if (!slot) |
134 | 0 | return CKR_HOST_MEMORY; |
135 | | |
136 | 15.4k | list_append(&virtual_slots, slot); |
137 | 15.4k | if (0 != list_init(&slot->objects)) { |
138 | 0 | return CKR_HOST_MEMORY; |
139 | 0 | } |
140 | 15.4k | list_attributes_seeker(&slot->objects, object_list_seeker); |
141 | | |
142 | 15.4k | if (0 != list_init(&slot->logins)) { |
143 | 0 | return CKR_HOST_MEMORY; |
144 | 0 | } |
145 | 15.4k | } else { |
146 | 0 | DEBUG_VSS(slot, "Reusing this old slot"); |
147 | | |
148 | | /* reuse the old list of logins/objects since they should be empty */ |
149 | 0 | list_t logins = slot->logins; |
150 | 0 | list_t objects = slot->objects; |
151 | |
|
152 | 0 | memset(slot, 0, sizeof *slot); |
153 | |
|
154 | 0 | slot->logins = logins; |
155 | 0 | slot->objects = objects; |
156 | 0 | } |
157 | | |
158 | 15.4k | slot->login_user = -1; |
159 | 15.4k | slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot); |
160 | 15.4k | init_slot_info(&slot->slot_info, reader); |
161 | 15.4k | slot->reader = reader; |
162 | | |
163 | 15.4k | DEBUG_VSS(slot, "Finished initializing this slot"); |
164 | | |
165 | 15.4k | return CKR_OK; |
166 | 15.4k | } |
167 | | |
168 | | void sc_pkcs11_card_free(struct sc_pkcs11_card *p11card) |
169 | 20.6k | { |
170 | 20.6k | if (p11card) { |
171 | 15.4k | size_t i; |
172 | 15.4k | if (p11card->framework && p11card->framework->unbind) |
173 | 12.3k | p11card->framework->unbind(p11card); |
174 | 15.4k | sc_disconnect_card(p11card->card); |
175 | 139k | for (i=0; i < p11card->nmechanisms; ++i) { |
176 | 124k | if (p11card->mechanisms[i]->free_mech_data) { |
177 | 93.7k | p11card->mechanisms[i]->free_mech_data(p11card->mechanisms[i]->mech_data); |
178 | 93.7k | } |
179 | 124k | free(p11card->mechanisms[i]); |
180 | 124k | } |
181 | 15.4k | free(p11card->mechanisms); |
182 | 15.4k | free(p11card); |
183 | 15.4k | } |
184 | 20.6k | } |
185 | | |
186 | | CK_RV card_removed(sc_reader_t * reader) |
187 | 15.4k | { |
188 | 15.4k | unsigned int i; |
189 | 15.4k | struct sc_pkcs11_card *p11card = NULL; |
190 | | /* Mark all slots as "token not present" */ |
191 | 15.4k | sc_log(context, "%s: card removed", reader->name); |
192 | | |
193 | | |
194 | 30.8k | for (i=0; i < list_size(&virtual_slots); i++) { |
195 | 15.4k | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
196 | 15.4k | if (slot->reader == reader) { |
197 | | /* Save the "card" object */ |
198 | 15.4k | if (slot->p11card) |
199 | 10.1k | p11card = slot->p11card; |
200 | 15.4k | slot_token_removed(slot->id); |
201 | 15.4k | } |
202 | 15.4k | } |
203 | | |
204 | 15.4k | sc_pkcs11_card_free(p11card); |
205 | | |
206 | 15.4k | return CKR_OK; |
207 | 15.4k | } |
208 | | |
209 | | |
210 | | CK_RV card_detect(sc_reader_t *reader) |
211 | 1.13k | { |
212 | 1.13k | struct sc_pkcs11_card *p11card = NULL; |
213 | 1.13k | int free_p11card = 0; |
214 | 1.13k | int rc; |
215 | 1.13k | CK_RV rv; |
216 | 1.13k | unsigned int i; |
217 | 1.13k | int j; |
218 | 1.13k | static int retry = 3; |
219 | | |
220 | 1.13k | sc_log(context, "%s: Detecting smart card", reader->name); |
221 | | /* Check if someone inserted a card */ |
222 | 1.13k | again: |
223 | 1.13k | rc = sc_detect_card_presence(reader); |
224 | 1.13k | if (rc < 0) { |
225 | 1.13k | sc_log(context, "%s: failed, %s", reader->name, sc_strerror(rc)); |
226 | 1.13k | return sc_to_cryptoki_error(rc, NULL); |
227 | 1.13k | } |
228 | 0 | if (rc == 0) { |
229 | 0 | sc_log(context, "%s: card absent", reader->name); |
230 | 0 | card_removed(reader); /* Release all resources */ |
231 | 0 | return CKR_TOKEN_NOT_PRESENT; |
232 | 0 | } |
233 | | |
234 | | /* If the card was changed, disconnect the current one */ |
235 | 0 | if (rc & SC_READER_CARD_CHANGED) { |
236 | 0 | sc_log(context, "%s: Card changed", reader->name); |
237 | | /* The following should never happen - but if it |
238 | | * does we'll be stuck in an endless loop. |
239 | | * So better be fussy.*/ |
240 | 0 | card_removed(reader); |
241 | 0 | if (!retry--) { |
242 | 0 | retry = 3; |
243 | 0 | return CKR_TOKEN_NOT_PRESENT; |
244 | 0 | } |
245 | 0 | goto again; |
246 | 0 | } |
247 | | |
248 | | /* Locate a slot related to the reader */ |
249 | 0 | for (i=0; i<list_size(&virtual_slots); i++) { |
250 | 0 | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
251 | 0 | if (slot->reader == reader) { |
252 | 0 | p11card = slot->p11card; |
253 | 0 | break; |
254 | 0 | } |
255 | 0 | } |
256 | | |
257 | | /* Detect the card if it's not known already */ |
258 | 0 | if (p11card == NULL) { |
259 | 0 | sc_log(context, "%s: First seen the card ", reader->name); |
260 | 0 | p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card)); |
261 | 0 | if (!p11card) |
262 | 0 | return CKR_HOST_MEMORY; |
263 | 0 | free_p11card = 1; |
264 | 0 | p11card->reader = reader; |
265 | 0 | } |
266 | | |
267 | 0 | if (p11card->card == NULL) { |
268 | 0 | sc_log(context, "%s: Connecting ... ", reader->name); |
269 | 0 | rc = sc_connect_card(reader, &p11card->card); |
270 | 0 | if (rc != SC_SUCCESS) { |
271 | 0 | sc_log(context, "%s: SC connect card error %i", reader->name, rc); |
272 | 0 | rv = sc_to_cryptoki_error(rc, NULL); |
273 | 0 | goto fail; |
274 | 0 | } |
275 | | |
276 | | /* escape commands are only guaranteed to be working with a card |
277 | | * inserted. That's why by now, after sc_connect_card() the reader's |
278 | | * metadata may have changed. We re-initialize the metadata for every |
279 | | * slot of this reader here. */ |
280 | 0 | if (reader->flags & SC_READER_ENABLE_ESCAPE) { |
281 | 0 | for (i = 0; i<list_size(&virtual_slots); i++) { |
282 | 0 | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
283 | 0 | if (slot->reader == reader) |
284 | 0 | init_slot_info(&slot->slot_info, reader); |
285 | 0 | } |
286 | 0 | } |
287 | |
|
288 | 0 | sc_log(context, "%s: Connected SC card %p", reader->name, p11card->card); |
289 | 0 | } |
290 | | |
291 | | /* Detect the framework */ |
292 | 0 | if (p11card->framework == NULL) { |
293 | 0 | struct sc_app_info *app_generic = sc_pkcs15_get_application_by_type(p11card->card, "generic"); |
294 | |
|
295 | 0 | sc_log(context, "%s: Detecting Framework. %i on-card applications", reader->name, p11card->card->app_count); |
296 | 0 | sc_log(context, "%s: generic application %s", reader->name, app_generic ? app_generic->label : "<none>"); |
297 | |
|
298 | 0 | for (i = 0; frameworks[i]; i++) |
299 | 0 | if (frameworks[i]->bind != NULL) |
300 | 0 | break; |
301 | | /*TODO: only first framework is used: pkcs15init framework is not reachable here */ |
302 | 0 | if (frameworks[i] == NULL) { |
303 | 0 | rv = CKR_GENERAL_ERROR; |
304 | 0 | goto fail; |
305 | 0 | } |
306 | | |
307 | 0 | p11card->framework = frameworks[i]; |
308 | | |
309 | | /* Initialize framework */ |
310 | 0 | sc_log(context, "%s: Detected framework %d. Creating tokens.", reader->name, i); |
311 | | /* Bind 'generic' application or (emulated?) card without applications */ |
312 | 0 | if (app_generic || !p11card->card->app_count) { |
313 | 0 | scconf_block *conf_block = NULL; |
314 | 0 | int enable_InitToken = 0; |
315 | |
|
316 | 0 | conf_block = sc_match_atr_block(p11card->card->ctx, NULL, |
317 | 0 | &p11card->reader->atr); |
318 | 0 | if (!conf_block) /* check default block */ |
319 | 0 | conf_block = sc_get_conf_block(context, |
320 | 0 | "framework", "pkcs15", 1); |
321 | |
|
322 | 0 | enable_InitToken = scconf_get_bool(conf_block, |
323 | 0 | "pkcs11_enable_InitToken", 0); |
324 | |
|
325 | 0 | sc_log(context, "%s: Try to bind 'generic' token.", reader->name); |
326 | 0 | rv = frameworks[i]->bind(p11card, app_generic); |
327 | 0 | if (rv == CKR_TOKEN_NOT_RECOGNIZED && enable_InitToken) { |
328 | 0 | sc_log(context, "%s: 'InitToken' enabled -- accept non-binded card", reader->name); |
329 | 0 | rv = CKR_OK; |
330 | 0 | } |
331 | 0 | if (rv != CKR_OK) { |
332 | 0 | sc_log(context, |
333 | 0 | "%s: cannot bind 'generic' token: rv 0x%lX", |
334 | 0 | reader->name, rv); |
335 | 0 | goto fail; |
336 | 0 | } |
337 | | |
338 | 0 | sc_log(context, "%s: Creating 'generic' token.", reader->name); |
339 | 0 | rv = frameworks[i]->create_tokens(p11card, app_generic); |
340 | 0 | if (rv != CKR_OK) { |
341 | 0 | sc_log(context, |
342 | 0 | "%s: create 'generic' token error 0x%lX", |
343 | 0 | reader->name, rv); |
344 | 0 | goto fail; |
345 | 0 | } |
346 | | /* p11card is now bound to some slot */ |
347 | 0 | free_p11card = 0; |
348 | 0 | } |
349 | | |
350 | | /* Now bind the rest of applications that are not 'generic' */ |
351 | 0 | for (j = 0; j < p11card->card->app_count; j++) { |
352 | 0 | struct sc_app_info *app_info = p11card->card->app[j]; |
353 | 0 | char *app_name = app_info ? app_info->label : "<anonymous>"; |
354 | |
|
355 | 0 | if (app_generic && app_generic == p11card->card->app[j]) |
356 | 0 | continue; |
357 | | |
358 | 0 | sc_log(context, "%s: Binding %s token.", reader->name, app_name); |
359 | 0 | rv = frameworks[i]->bind(p11card, app_info); |
360 | 0 | if (rv != CKR_OK) { |
361 | 0 | sc_log(context, "%s: bind %s token error Ox%lX", |
362 | 0 | reader->name, app_name, rv); |
363 | 0 | continue; |
364 | 0 | } |
365 | | |
366 | 0 | sc_log(context, "%s: Creating %s token.", reader->name, app_name); |
367 | 0 | rv = frameworks[i]->create_tokens(p11card, app_info); |
368 | 0 | if (rv != CKR_OK) { |
369 | 0 | sc_log(context, |
370 | 0 | "%s: create %s token error 0x%lX", |
371 | 0 | reader->name, app_name, rv); |
372 | 0 | goto fail; |
373 | 0 | } |
374 | | /* p11card is now bound to some slot */ |
375 | 0 | free_p11card = 0; |
376 | 0 | } |
377 | 0 | } |
378 | | |
379 | 0 | sc_log(context, "%s: Detection ended", reader->name); |
380 | 0 | rv = CKR_OK; |
381 | |
|
382 | 0 | fail: |
383 | 0 | if (free_p11card) { |
384 | 0 | sc_pkcs11_card_free(p11card); |
385 | 0 | } |
386 | |
|
387 | 0 | return rv; |
388 | 0 | } |
389 | | |
390 | | |
391 | | CK_RV |
392 | | card_detect_all(void) |
393 | 15.4k | { |
394 | 15.4k | unsigned int i, j; |
395 | | |
396 | 15.4k | sc_log(context, "Detect all cards"); |
397 | | /* Detect cards in all initialized readers */ |
398 | 15.4k | for (i=0; i< sc_ctx_get_reader_count(context); i++) { |
399 | 0 | sc_reader_t *reader = sc_ctx_get_reader(context, i); |
400 | |
|
401 | 0 | if (reader->flags & SC_READER_REMOVED) { |
402 | 0 | card_removed(reader); |
403 | | /* do not remove slots related to this reader which would be |
404 | | * possible according to PKCS#11 2.20 and later, because NSS can't |
405 | | * handle a shrinking slot list |
406 | | * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ |
407 | | |
408 | | /* Instead, remove the relation between reader and slot */ |
409 | 0 | for (j = 0; j<list_size(&virtual_slots); j++) { |
410 | 0 | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j); |
411 | 0 | if (slot->reader == reader) { |
412 | 0 | slot->reader = NULL; |
413 | 0 | } |
414 | 0 | } |
415 | 0 | } else { |
416 | | /* Locate a slot related to the reader */ |
417 | 0 | int found = 0; |
418 | 0 | for (j = 0; j<list_size(&virtual_slots); j++) { |
419 | 0 | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, j); |
420 | 0 | if (slot->reader == reader) { |
421 | 0 | found = 1; |
422 | 0 | break; |
423 | 0 | } |
424 | 0 | } |
425 | 0 | if (!found) { |
426 | 0 | for (j = 0; j < sc_pkcs11_conf.slots_per_card; j++) { |
427 | 0 | CK_RV rv = create_slot(reader); |
428 | 0 | if (rv != CKR_OK) |
429 | 0 | return rv; |
430 | 0 | } |
431 | 0 | } |
432 | 0 | card_detect(reader); |
433 | 0 | } |
434 | 0 | } |
435 | 15.4k | sc_log(context, "All cards detected"); |
436 | 15.4k | return CKR_OK; |
437 | 15.4k | } |
438 | | |
439 | | /* Allocates an existing slot to a card */ |
440 | | CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * p11card) |
441 | 10.5k | { |
442 | 10.5k | unsigned int i; |
443 | 10.5k | struct sc_pkcs11_slot *tmp_slot = NULL; |
444 | | |
445 | | /* Locate a free slot for this reader */ |
446 | 11.0k | for (i=0; i< list_size(&virtual_slots); i++) { |
447 | 10.5k | tmp_slot = (struct sc_pkcs11_slot *)list_get_at(&virtual_slots, i); |
448 | 10.5k | if (tmp_slot->reader == p11card->reader && tmp_slot->p11card == NULL) |
449 | 10.1k | break; |
450 | 10.5k | } |
451 | 10.5k | if (!tmp_slot || (i == list_size(&virtual_slots))) |
452 | 409 | return CKR_FUNCTION_FAILED; |
453 | 10.1k | sc_log(context, "Allocated slot 0x%lx for card in reader %s", tmp_slot->id, p11card->reader->name); |
454 | 10.1k | tmp_slot->p11card = p11card; |
455 | 10.1k | tmp_slot->events = SC_EVENT_CARD_INSERTED; |
456 | 10.1k | *slot = tmp_slot; |
457 | 10.1k | return CKR_OK; |
458 | 10.5k | } |
459 | | |
460 | | CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot) |
461 | 28.5k | { |
462 | 28.5k | if (context == NULL) |
463 | 0 | return CKR_CRYPTOKI_NOT_INITIALIZED; |
464 | | |
465 | 28.5k | *slot = list_seek(&virtual_slots, &id); /* FIXME: check for null? */ |
466 | 28.5k | if (!*slot) |
467 | 0 | return CKR_SLOT_ID_INVALID; |
468 | 28.5k | return CKR_OK; |
469 | 28.5k | } |
470 | | |
471 | | CK_RV slot_get_token(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot) |
472 | 13.1k | { |
473 | 13.1k | CK_RV rv; |
474 | | |
475 | 13.1k | sc_log(context, "Slot(id=0x%lX): get token", id); |
476 | 13.1k | rv = slot_get_slot(id, slot); |
477 | 13.1k | if (rv != CKR_OK) |
478 | 0 | return rv; |
479 | | |
480 | 13.1k | if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) { |
481 | 1.13k | if ((*slot)->reader == NULL) |
482 | 0 | return CKR_TOKEN_NOT_PRESENT; |
483 | 1.13k | sc_log(context, "Slot(id=0x%lX): get token: now detect card", id); |
484 | 1.13k | rv = card_detect((*slot)->reader); |
485 | 1.13k | if (rv != CKR_OK) |
486 | 1.13k | return rv; |
487 | 1.13k | } |
488 | | |
489 | 11.9k | if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) { |
490 | 0 | sc_log(context, "card detected, but slot not presenting token"); |
491 | 0 | return CKR_TOKEN_NOT_PRESENT; |
492 | 0 | } |
493 | 11.9k | sc_log(context, "Slot-get-token returns OK"); |
494 | 11.9k | return CKR_OK; |
495 | 11.9k | } |
496 | | |
497 | | CK_RV slot_token_removed(CK_SLOT_ID id) |
498 | 15.4k | { |
499 | 15.4k | CK_RV rv; |
500 | 15.4k | int token_was_present; |
501 | 15.4k | struct sc_pkcs11_slot *slot; |
502 | 15.4k | struct sc_pkcs11_object *object; |
503 | | |
504 | 15.4k | sc_log(context, "slot_token_removed(0x%lx)", id); |
505 | 15.4k | rv = slot_get_slot(id, &slot); |
506 | 15.4k | if (rv != CKR_OK) |
507 | 0 | return rv; |
508 | | |
509 | 15.4k | token_was_present = (slot->slot_info.flags & CKF_TOKEN_PRESENT); |
510 | | |
511 | | /* Terminate active sessions */ |
512 | 15.4k | sc_pkcs11_close_all_sessions(id); |
513 | | |
514 | 41.4k | while ((object = list_fetch(&slot->objects))) { |
515 | 26.0k | if (object->ops->release) |
516 | 26.0k | object->ops->release(object); |
517 | 26.0k | } |
518 | | |
519 | | /* Release framework stuff */ |
520 | 15.4k | if (slot->p11card != NULL) { |
521 | 10.1k | if (slot->fw_data != NULL && slot->p11card->framework != NULL |
522 | 5.11k | && slot->p11card->framework->release_token != NULL) { |
523 | 5.11k | slot->p11card->framework->release_token(slot->p11card, slot->fw_data); |
524 | 5.11k | slot->fw_data = NULL; |
525 | 5.11k | } |
526 | 10.1k | slot->p11card = NULL; |
527 | 10.1k | } |
528 | | |
529 | | /* Reset relevant slot properties */ |
530 | 15.4k | slot->slot_info.flags &= ~CKF_TOKEN_PRESENT; |
531 | 15.4k | slot->login_user = -1; |
532 | 15.4k | slot->profile = NULL; |
533 | 15.4k | pop_all_login_states(slot); |
534 | | |
535 | 15.4k | if (token_was_present) |
536 | 10.1k | slot->events = SC_EVENT_CARD_REMOVED; |
537 | | |
538 | 15.4k | memset(&slot->token_info, 0, sizeof slot->token_info); |
539 | | |
540 | 15.4k | return CKR_OK; |
541 | 15.4k | } |
542 | | |
543 | | /* Called from C_WaitForSlotEvent */ |
544 | | CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask) |
545 | 0 | { |
546 | 0 | unsigned int i; |
547 | 0 | LOG_FUNC_CALLED(context); |
548 | |
|
549 | 0 | card_detect_all(); |
550 | 0 | for (i=0; i<list_size(&virtual_slots); i++) { |
551 | 0 | sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
552 | 0 | sc_log(context, "slot 0x%lx token: %lu events: 0x%02X", |
553 | 0 | slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT), |
554 | 0 | slot->events); |
555 | 0 | if ((slot->events & SC_EVENT_CARD_INSERTED) |
556 | 0 | && !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) { |
557 | | /* If a token has not been initialized, clear the inserted event */ |
558 | 0 | slot->events &= ~SC_EVENT_CARD_INSERTED; |
559 | 0 | } |
560 | 0 | sc_log(context, "mask: 0x%02X events: 0x%02X result: %d", mask, slot->events, (slot->events & mask)); |
561 | |
|
562 | 0 | if (slot->events & mask) { |
563 | 0 | slot->events &= ~mask; |
564 | 0 | *idp = slot->id; |
565 | 0 | LOG_FUNC_RETURN(context, CKR_OK); |
566 | 0 | } |
567 | 0 | } |
568 | 0 | LOG_FUNC_RETURN(context, CKR_NO_EVENT); |
569 | 0 | } |