/src/opensc/src/pkcs11/pkcs11-global.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * pkcs11-global.c: PKCS#11 module level functions and function table |
3 | | * |
4 | | * Copyright (C) 2002 Timo Teräs <timo.teras@iki.fi> |
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 | | |
21 | | #include "config.h" |
22 | | |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | #ifdef HAVE_SYS_TIME_H |
26 | | #include <sys/time.h> |
27 | | #endif |
28 | | |
29 | | #ifdef PKCS11_THREAD_LOCKING |
30 | | #if defined(HAVE_PTHREAD) |
31 | | #include <pthread.h> |
32 | | #elif defined(_WIN32) |
33 | | #include <windows.h> |
34 | | #endif |
35 | | #endif /* PKCS11_THREAD_LOCKING */ |
36 | | |
37 | | #include "sc-pkcs11.h" |
38 | | #include "ui/notify.h" |
39 | | |
40 | | #ifdef ENABLE_OPENSSL |
41 | | #include <openssl/crypto.h> |
42 | | #include "libopensc/sc-ossl-compat.h" |
43 | | #endif |
44 | | #ifdef ENABLE_OPENPACE |
45 | | #include <eac/eac.h> |
46 | | #endif |
47 | | |
48 | | #ifndef MODULE_APP_NAME |
49 | 15.4k | #define MODULE_APP_NAME "opensc-pkcs11" |
50 | | #endif |
51 | | |
52 | | sc_context_t *context = NULL; |
53 | | struct sc_pkcs11_config sc_pkcs11_conf; |
54 | | list_t sessions; |
55 | | list_t virtual_slots; |
56 | | #if !defined(_WIN32) |
57 | | pid_t initialized_pid = (pid_t)-1; |
58 | | #endif |
59 | | static int in_finalize = 0; |
60 | | extern CK_FUNCTION_LIST pkcs11_function_list; |
61 | | extern CK_FUNCTION_LIST_3_0 pkcs11_function_list_3_0; |
62 | | int nesting = 0; |
63 | | |
64 | | #ifdef PKCS11_THREAD_LOCKING |
65 | | |
66 | | #if defined(HAVE_PTHREAD) |
67 | | |
68 | | /* mutex used to control C_Initilize creation of mutexes */ |
69 | | static pthread_mutex_t c_initialize_m = PTHREAD_MUTEX_INITIALIZER; |
70 | 46.4k | #define C_INITIALIZE_M_LOCK pthread_mutex_lock(&c_initialize_m); |
71 | 46.4k | #define C_INITIALIZE_M_UNLOCK pthread_mutex_unlock(&c_initialize_m); |
72 | | |
73 | | CK_RV mutex_create(void **mutex) |
74 | 0 | { |
75 | 0 | pthread_mutex_t *m; |
76 | |
|
77 | 0 | m = calloc(1, sizeof(*m)); |
78 | 0 | if (m == NULL) |
79 | 0 | return CKR_GENERAL_ERROR; |
80 | 0 | pthread_mutex_init(m, NULL); |
81 | 0 | *mutex = m; |
82 | 0 | return CKR_OK; |
83 | 0 | } |
84 | | |
85 | | CK_RV mutex_lock(void *p) |
86 | 0 | { |
87 | 0 | if (pthread_mutex_lock((pthread_mutex_t *) p) == 0) |
88 | 0 | return CKR_OK; |
89 | 0 | else |
90 | 0 | return CKR_GENERAL_ERROR; |
91 | 0 | } |
92 | | |
93 | | CK_RV mutex_unlock(void *p) |
94 | 0 | { |
95 | 0 | if (pthread_mutex_unlock((pthread_mutex_t *) p) == 0) |
96 | 0 | return CKR_OK; |
97 | 0 | else |
98 | 0 | return CKR_GENERAL_ERROR; |
99 | 0 | } |
100 | | |
101 | | CK_RV mutex_destroy(void *p) |
102 | 0 | { |
103 | 0 | pthread_mutex_destroy((pthread_mutex_t *) p); |
104 | 0 | free(p); |
105 | 0 | return CKR_OK; |
106 | 0 | } |
107 | | |
108 | | static CK_C_INITIALIZE_ARGS _def_locks = { |
109 | | mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL }; |
110 | | #define HAVE_OS_LOCKING |
111 | | |
112 | | #elif defined(_WIN32) |
113 | | CRITICAL_SECTION c_initialize_cs = {0}; |
114 | | #define C_INITIALIZE_M_LOCK EnterCriticalSection(&c_initialize_cs); |
115 | | #define C_INITIALIZE_M_UNLOCK LeaveCriticalSection(&c_initialize_cs); |
116 | | |
117 | | CK_RV mutex_create(void **mutex) |
118 | | { |
119 | | CRITICAL_SECTION *m; |
120 | | |
121 | | m = calloc(1, sizeof(*m)); |
122 | | if (m == NULL) |
123 | | return CKR_GENERAL_ERROR; |
124 | | InitializeCriticalSection(m); |
125 | | *mutex = m; |
126 | | return CKR_OK; |
127 | | } |
128 | | |
129 | | CK_RV mutex_lock(void *p) |
130 | | { |
131 | | EnterCriticalSection((CRITICAL_SECTION *) p); |
132 | | return CKR_OK; |
133 | | } |
134 | | |
135 | | |
136 | | CK_RV mutex_unlock(void *p) |
137 | | { |
138 | | LeaveCriticalSection((CRITICAL_SECTION *) p); |
139 | | return CKR_OK; |
140 | | } |
141 | | |
142 | | |
143 | | CK_RV mutex_destroy(void *p) |
144 | | { |
145 | | DeleteCriticalSection((CRITICAL_SECTION *) p); |
146 | | free(p); |
147 | | return CKR_OK; |
148 | | } |
149 | | |
150 | | static CK_C_INITIALIZE_ARGS _def_locks = { |
151 | | mutex_create, mutex_destroy, mutex_lock, mutex_unlock, 0, NULL }; |
152 | | #define HAVE_OS_LOCKING |
153 | | |
154 | | #endif |
155 | | |
156 | | #else /* PKCS11_THREAD_LOCKING */ |
157 | | #define C_INITIALIZE_M_LOCK |
158 | | #define C_INITIALIZE_M_UNLOCK |
159 | | |
160 | | #endif /* PKCS11_THREAD_LOCKING */ |
161 | | |
162 | | static CK_C_INITIALIZE_ARGS_PTR global_locking; |
163 | | static CK_C_INITIALIZE_ARGS app_locking = { |
164 | | NULL, NULL, NULL, NULL, 0, NULL }; |
165 | | static void *global_lock = NULL; |
166 | | #ifdef HAVE_OS_LOCKING |
167 | | static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = &_def_locks; |
168 | | #else |
169 | | static CK_C_INITIALIZE_ARGS_PTR default_mutex_funcs = NULL; |
170 | | #endif |
171 | | |
172 | | /* wrapper for the locking functions for libopensc */ |
173 | | static int sc_create_mutex(void **m) |
174 | 30.9k | { |
175 | 30.9k | if (global_locking == NULL) |
176 | 30.9k | return SC_SUCCESS; |
177 | 0 | if (global_locking->CreateMutex(m) == CKR_OK) |
178 | 0 | return SC_SUCCESS; |
179 | 0 | else |
180 | 0 | return SC_ERROR_INTERNAL; |
181 | 0 | } |
182 | | |
183 | | static int sc_lock_mutex(void *m) |
184 | 1.12M | { |
185 | 1.12M | if (global_locking == NULL) |
186 | 1.12M | return SC_SUCCESS; |
187 | 0 | if (global_locking->LockMutex(m) == CKR_OK) |
188 | 0 | return SC_SUCCESS; |
189 | 0 | else |
190 | 0 | return SC_ERROR_INTERNAL; |
191 | 0 | } |
192 | | |
193 | | static int sc_unlock_mutex(void *m) |
194 | 1.12M | { |
195 | 1.12M | if (global_locking == NULL) |
196 | 1.12M | return SC_SUCCESS; |
197 | 0 | if (global_locking->UnlockMutex(m) == CKR_OK) |
198 | 0 | return SC_SUCCESS; |
199 | 0 | else |
200 | 0 | return SC_ERROR_INTERNAL; |
201 | |
|
202 | 0 | } |
203 | | |
204 | | static int sc_destroy_mutex(void *m) |
205 | 0 | { |
206 | 0 | if (global_locking == NULL) |
207 | 0 | return SC_SUCCESS; |
208 | 0 | if (global_locking->DestroyMutex(m) == CKR_OK) |
209 | 0 | return SC_SUCCESS; |
210 | 0 | else |
211 | 0 | return SC_ERROR_INTERNAL; |
212 | 0 | } |
213 | | |
214 | | static sc_thread_context_t sc_thread_ctx = { |
215 | | 0, sc_create_mutex, sc_lock_mutex, |
216 | | sc_unlock_mutex, sc_destroy_mutex, NULL |
217 | | }; |
218 | | |
219 | | /* simclist helpers to locate interesting objects by ID */ |
220 | 25.2k | static int session_list_seeker(const void *el, const void *key) { |
221 | 25.2k | const struct sc_pkcs11_session *session = (struct sc_pkcs11_session *)el; |
222 | 25.2k | if ((el == NULL) || (key == NULL)) |
223 | 0 | return 0; |
224 | 25.2k | if (session->handle == *(CK_SESSION_HANDLE*)key) |
225 | 25.2k | return 1; |
226 | 0 | return 0; |
227 | 25.2k | } |
228 | 28.6k | static int slot_list_seeker(const void *el, const void *key) { |
229 | 28.6k | const struct sc_pkcs11_slot *slot = (struct sc_pkcs11_slot *)el; |
230 | 28.6k | if ((el == NULL) || (key == NULL)) |
231 | 0 | return 0; |
232 | 28.6k | if (slot->id == *(CK_SLOT_ID *)key) |
233 | 28.6k | return 1; |
234 | 0 | return 0; |
235 | 28.6k | } |
236 | | |
237 | | #ifndef _WIN32 |
238 | | __attribute__((constructor)) |
239 | | #endif |
240 | | int module_init() |
241 | 2 | { |
242 | | #ifdef _WIN32 |
243 | | InitializeCriticalSection(&c_initialize_cs); |
244 | | #endif |
245 | 2 | sc_notify_init(); |
246 | 2 | return 1; |
247 | 2 | } |
248 | | |
249 | | #ifndef _WIN32 |
250 | | __attribute__((destructor)) |
251 | | #endif |
252 | | int module_close() |
253 | 0 | { |
254 | 0 | sc_notify_close(); |
255 | | #if defined(ENABLE_OPENSSL) && defined(OPENSSL_SECURE_MALLOC_SIZE) && !defined(LIBRESSL_VERSION_NUMBER) |
256 | | CRYPTO_secure_malloc_done(); |
257 | | #endif |
258 | | #ifdef ENABLE_OPENPACE |
259 | | EAC_cleanup(); |
260 | | #endif |
261 | | #ifdef _WIN32 |
262 | | DeleteCriticalSection(&c_initialize_cs); |
263 | | #endif |
264 | 0 | return 1; |
265 | 0 | } |
266 | | |
267 | | #ifdef _WIN32 |
268 | | BOOL APIENTRY DllMain( HINSTANCE hinstDLL, |
269 | | DWORD ul_reason_for_call, |
270 | | LPVOID lpReserved |
271 | | ) |
272 | | { |
273 | | switch (ul_reason_for_call) |
274 | | { |
275 | | case DLL_PROCESS_ATTACH: |
276 | | if (!module_init()) |
277 | | return FALSE; |
278 | | break; |
279 | | case DLL_PROCESS_DETACH: |
280 | | if (lpReserved == NULL) { |
281 | | if (!module_close()) |
282 | | return FALSE; |
283 | | } |
284 | | break; |
285 | | } |
286 | | return TRUE; |
287 | | } |
288 | | #endif |
289 | | |
290 | | CK_RV C_Initialize(CK_VOID_PTR pInitArgs) |
291 | 15.4k | { |
292 | 15.4k | CK_RV rv; |
293 | 15.4k | #if !defined(_WIN32) |
294 | 15.4k | pid_t current_pid; |
295 | 15.4k | #endif |
296 | 15.4k | int rc; |
297 | 15.4k | sc_context_param_t ctx_opts; |
298 | | |
299 | 15.4k | #if !defined(_WIN32) |
300 | | /* Handle fork() exception */ |
301 | 15.4k | C_INITIALIZE_M_LOCK |
302 | 15.4k | current_pid = getpid(); |
303 | 15.4k | if (current_pid != initialized_pid) { |
304 | 1 | if (context && CKR_OK == sc_pkcs11_lock()) { |
305 | 0 | context->flags |= SC_CTX_FLAG_TERMINATE; |
306 | 0 | sc_pkcs11_unlock(); |
307 | 0 | } |
308 | 1 | C_Finalize(NULL_PTR); |
309 | 1 | } |
310 | 15.4k | initialized_pid = current_pid; |
311 | 15.4k | in_finalize = 0; |
312 | 15.4k | C_INITIALIZE_M_UNLOCK |
313 | 15.4k | #endif |
314 | | |
315 | | /* protect from nesting */ |
316 | 15.4k | C_INITIALIZE_M_LOCK |
317 | 15.4k | nesting++; |
318 | 15.4k | if (nesting > 1) { |
319 | 0 | nesting--; |
320 | 0 | C_INITIALIZE_M_UNLOCK |
321 | 0 | return CKR_GENERAL_ERROR; |
322 | 0 | } |
323 | 15.4k | C_INITIALIZE_M_UNLOCK |
324 | | /* protect from nesting */ |
325 | | |
326 | | /* protect from multiple threads tryng to setup locking */ |
327 | 15.4k | C_INITIALIZE_M_LOCK |
328 | | |
329 | 15.4k | if (context != NULL) { |
330 | 0 | if (CKR_OK == sc_pkcs11_lock()) { |
331 | 0 | sc_log(context, "C_Initialize(): Cryptoki already initialized\n"); |
332 | 0 | sc_pkcs11_unlock(); |
333 | 0 | } |
334 | 0 | nesting--; |
335 | 0 | C_INITIALIZE_M_UNLOCK |
336 | 0 | return CKR_CRYPTOKI_ALREADY_INITIALIZED; |
337 | 0 | } |
338 | | |
339 | 15.4k | rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pInitArgs); |
340 | 15.4k | if (rv != CKR_OK) |
341 | 0 | goto out; |
342 | | |
343 | | /* set context options */ |
344 | 15.4k | memset(&ctx_opts, 0, sizeof(sc_context_param_t)); |
345 | 15.4k | ctx_opts.ver = 0; |
346 | 15.4k | ctx_opts.app_name = MODULE_APP_NAME; |
347 | 15.4k | ctx_opts.thread_ctx = &sc_thread_ctx; |
348 | | |
349 | 15.4k | rc = sc_context_create(&context, &ctx_opts); |
350 | 15.4k | if (rc != SC_SUCCESS) { |
351 | 0 | rv = CKR_GENERAL_ERROR; |
352 | 0 | goto out; |
353 | 0 | } |
354 | | |
355 | | /* Load configuration */ |
356 | 15.4k | load_pkcs11_parameters(&sc_pkcs11_conf, context); |
357 | | |
358 | | /* List of sessions */ |
359 | 15.4k | if (0 != list_init(&sessions)) { |
360 | 0 | rv = CKR_HOST_MEMORY; |
361 | 0 | goto out; |
362 | 0 | } |
363 | 15.4k | list_attributes_seeker(&sessions, session_list_seeker); |
364 | | |
365 | | /* List of slots */ |
366 | 15.4k | if (0 != list_init(&virtual_slots)) { |
367 | 0 | rv = CKR_HOST_MEMORY; |
368 | 0 | goto out; |
369 | 0 | } |
370 | 15.4k | list_attributes_seeker(&virtual_slots, slot_list_seeker); |
371 | | |
372 | 15.4k | card_detect_all(); |
373 | | |
374 | 15.4k | out: |
375 | 15.4k | if (context != NULL) |
376 | 15.4k | SC_LOG_RV("C_Initialize() = %s", rv); |
377 | | |
378 | 15.4k | if (rv != CKR_OK) { |
379 | 0 | if (context != NULL) { |
380 | 0 | sc_release_context(context); |
381 | 0 | context = NULL; |
382 | 0 | } |
383 | | /* Release and destroy the mutex */ |
384 | 0 | sc_pkcs11_free_lock(); |
385 | 0 | } |
386 | | |
387 | | /* protect from multiple threads tryng to setup locking */ |
388 | 15.4k | nesting--; |
389 | 15.4k | C_INITIALIZE_M_UNLOCK |
390 | | |
391 | 15.4k | return rv; |
392 | 15.4k | } |
393 | | |
394 | | CK_RV C_Finalize(CK_VOID_PTR pReserved) |
395 | 15.4k | { |
396 | 15.4k | int i; |
397 | 15.4k | void *p; |
398 | 15.4k | sc_pkcs11_slot_t *slot; |
399 | 15.4k | CK_RV rv; |
400 | | |
401 | 15.4k | if (pReserved != NULL_PTR) |
402 | 0 | return CKR_ARGUMENTS_BAD; |
403 | | |
404 | 15.4k | #if !defined(_WIN32) |
405 | 15.4k | sc_notify_close(); |
406 | 15.4k | #endif |
407 | | |
408 | 15.4k | if (context == NULL) |
409 | 1 | return CKR_CRYPTOKI_NOT_INITIALIZED; |
410 | | |
411 | 15.4k | rv = sc_pkcs11_lock(); |
412 | 15.4k | if (rv != CKR_OK) |
413 | 0 | return rv; |
414 | | |
415 | 15.4k | sc_log(context, "C_Finalize()"); |
416 | | |
417 | | /* cancel pending calls */ |
418 | 15.4k | in_finalize = 1; |
419 | 15.4k | sc_cancel(context); |
420 | | /* remove all cards from readers */ |
421 | 30.9k | for (i=0; i < (int)sc_ctx_get_reader_count(context); i++) |
422 | 15.4k | card_removed(sc_ctx_get_reader(context, i)); |
423 | | |
424 | 15.4k | while ((p = list_fetch(&sessions))) |
425 | 0 | free(p); |
426 | 15.4k | list_destroy(&sessions); |
427 | | |
428 | 30.9k | while ((slot = list_fetch(&virtual_slots))) { |
429 | 15.4k | list_destroy(&slot->objects); |
430 | 15.4k | list_destroy(&slot->logins); |
431 | 15.4k | free(slot); |
432 | 15.4k | } |
433 | 15.4k | list_destroy(&virtual_slots); |
434 | | |
435 | 15.4k | sc_release_context(context); |
436 | 15.4k | context = NULL; |
437 | | |
438 | | /* Release and destroy the mutex */ |
439 | 15.4k | sc_pkcs11_free_lock(); |
440 | | |
441 | 15.4k | return rv; |
442 | 15.4k | } |
443 | | |
444 | | CK_RV get_info_version(CK_INFO_PTR pInfo, CK_VERSION version) |
445 | 0 | { |
446 | 0 | CK_RV rv = CKR_OK; |
447 | |
|
448 | 0 | if (pInfo == NULL_PTR) |
449 | 0 | return CKR_ARGUMENTS_BAD; |
450 | | |
451 | 0 | rv = sc_pkcs11_lock(); |
452 | 0 | if (rv != CKR_OK) |
453 | 0 | return rv; |
454 | | |
455 | 0 | sc_log(context, "C_GetInfo()"); |
456 | |
|
457 | 0 | memset(pInfo, 0, sizeof(CK_INFO)); |
458 | 0 | pInfo->cryptokiVersion.major = version.major; |
459 | 0 | pInfo->cryptokiVersion.minor = version.minor; |
460 | 0 | strcpy_bp(pInfo->manufacturerID, |
461 | 0 | OPENSC_VS_FF_COMPANY_NAME, |
462 | 0 | sizeof(pInfo->manufacturerID)); |
463 | 0 | strcpy_bp(pInfo->libraryDescription, |
464 | 0 | OPENSC_VS_FF_PRODUCT_NAME, |
465 | 0 | sizeof(pInfo->libraryDescription)); |
466 | 0 | pInfo->libraryVersion.major = OPENSC_VERSION_MAJOR; |
467 | 0 | pInfo->libraryVersion.minor = OPENSC_VERSION_MINOR; |
468 | |
|
469 | 0 | sc_pkcs11_unlock(); |
470 | 0 | return rv; |
471 | 0 | } |
472 | | |
473 | | CK_RV C_GetInfoV2(CK_INFO_PTR pInfo) |
474 | 0 | { |
475 | 0 | CK_VERSION v = {2, 20}; |
476 | |
|
477 | 0 | return get_info_version(pInfo, v); |
478 | 0 | } |
479 | | |
480 | | CK_RV C_GetInfo(CK_INFO_PTR pInfo) |
481 | 0 | { |
482 | 0 | CK_VERSION v = {3, 0}; |
483 | |
|
484 | 0 | return get_info_version(pInfo, v); |
485 | 0 | } |
486 | | |
487 | | CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) |
488 | 0 | { |
489 | 0 | if (ppFunctionList == NULL_PTR) |
490 | 0 | return CKR_ARGUMENTS_BAD; |
491 | | |
492 | 0 | *ppFunctionList = &pkcs11_function_list; |
493 | 0 | return CKR_OK; |
494 | 0 | } |
495 | | |
496 | | CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token present */ |
497 | | CK_SLOT_ID_PTR pSlotList, /* receives the array of slot IDs */ |
498 | | CK_ULONG_PTR pulCount) /* receives the number of slots */ |
499 | 0 | { |
500 | 0 | CK_SLOT_ID_PTR found = NULL; |
501 | 0 | unsigned int i; |
502 | 0 | CK_ULONG numMatches; |
503 | 0 | sc_pkcs11_slot_t *slot; |
504 | 0 | sc_reader_t *prev_reader = NULL; |
505 | 0 | CK_RV rv; |
506 | |
|
507 | 0 | if (pulCount == NULL_PTR) |
508 | 0 | return CKR_ARGUMENTS_BAD; |
509 | | |
510 | 0 | rv = sc_pkcs11_lock(); |
511 | 0 | if (rv != CKR_OK) |
512 | 0 | return rv; |
513 | | |
514 | 0 | sc_log(context, "C_GetSlotList(token=%d, %s)", tokenPresent, |
515 | 0 | pSlotList==NULL_PTR? "plug-n-play":"refresh"); |
516 | 0 | DEBUG_VSS(NULL, "C_GetSlotList before ctx_detect_detect"); |
517 | | |
518 | | /* Slot list can only change in v2.20 */ |
519 | 0 | if (pSlotList == NULL_PTR) |
520 | 0 | sc_ctx_detect_readers(context); |
521 | |
|
522 | 0 | DEBUG_VSS(NULL, "C_GetSlotList after ctx_detect_readers"); |
523 | |
|
524 | 0 | card_detect_all(); |
525 | |
|
526 | 0 | if (list_empty(&virtual_slots)) { |
527 | 0 | sc_log(context, "returned 0 slots\n"); |
528 | 0 | *pulCount = 0; |
529 | 0 | rv = CKR_OK; |
530 | 0 | goto out; |
531 | 0 | } |
532 | | |
533 | 0 | found = calloc(list_size(&virtual_slots), sizeof(CK_SLOT_ID)); |
534 | |
|
535 | 0 | if (found == NULL) { |
536 | 0 | rv = CKR_HOST_MEMORY; |
537 | 0 | goto out; |
538 | 0 | } |
539 | | |
540 | 0 | prev_reader = NULL; |
541 | 0 | numMatches = 0; |
542 | 0 | for (i=0; i<list_size(&virtual_slots); i++) { |
543 | 0 | slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); |
544 | | /* the list of available slots contains: |
545 | | * - without token(s), at least one empty slot per reader; |
546 | | * - any slot with token; |
547 | | * - any slot that has already been seen; |
548 | | */ |
549 | 0 | if ((!tokenPresent && |
550 | 0 | (slot->reader != prev_reader || |
551 | 0 | slot->flags & SC_PKCS11_SLOT_FLAG_SEEN)) |
552 | 0 | || slot->slot_info.flags & CKF_TOKEN_PRESENT) { |
553 | 0 | found[numMatches++] = slot->id; |
554 | 0 | slot->flags |= SC_PKCS11_SLOT_FLAG_SEEN; |
555 | 0 | } |
556 | 0 | prev_reader = slot->reader; |
557 | 0 | } |
558 | 0 | DEBUG_VSS(NULL, "C_GetSlotList after card_detect_all"); |
559 | |
|
560 | 0 | if (pSlotList == NULL_PTR) { |
561 | 0 | sc_log(context, "was only a size inquiry (%lu)\n", numMatches); |
562 | 0 | *pulCount = numMatches; |
563 | 0 | rv = CKR_OK; |
564 | 0 | goto out; |
565 | 0 | } |
566 | 0 | DEBUG_VSS(NULL, "C_GetSlotList after slot->id reassigned"); |
567 | |
|
568 | 0 | if (*pulCount < numMatches) { |
569 | 0 | sc_log(context, "buffer was too small (needed %lu)\n", numMatches); |
570 | 0 | *pulCount = numMatches; |
571 | 0 | rv = CKR_BUFFER_TOO_SMALL; |
572 | 0 | goto out; |
573 | 0 | } |
574 | | |
575 | 0 | memcpy(pSlotList, found, numMatches * sizeof(CK_SLOT_ID)); |
576 | 0 | *pulCount = numMatches; |
577 | 0 | rv = CKR_OK; |
578 | |
|
579 | 0 | sc_log(context, "returned %lu slots\n", numMatches); |
580 | 0 | DEBUG_VSS(NULL, "Returning a new slot list"); |
581 | |
|
582 | 0 | out: |
583 | 0 | free (found); |
584 | 0 | sc_pkcs11_unlock(); |
585 | 0 | return rv; |
586 | 0 | } |
587 | | |
588 | | static sc_timestamp_t get_current_time(void) |
589 | 0 | { |
590 | 0 | #if HAVE_GETTIMEOFDAY |
591 | 0 | struct timeval tv; |
592 | 0 | struct timezone tz; |
593 | 0 | sc_timestamp_t curr; |
594 | |
|
595 | 0 | if (gettimeofday(&tv, &tz) != 0) |
596 | 0 | return 0; |
597 | | |
598 | 0 | curr = tv.tv_sec; |
599 | 0 | curr *= 1000; |
600 | 0 | curr += tv.tv_usec / 1000; |
601 | | #else |
602 | | struct _timeb time_buf; |
603 | | sc_timestamp_t curr; |
604 | | |
605 | | _ftime(&time_buf); |
606 | | |
607 | | curr = time_buf.time; |
608 | | curr *= 1000; |
609 | | curr += time_buf.millitm; |
610 | | #endif |
611 | |
|
612 | 0 | return curr; |
613 | 0 | } |
614 | | |
615 | | CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) |
616 | 0 | { |
617 | 0 | struct sc_pkcs11_slot *slot = NULL; |
618 | 0 | sc_timestamp_t now; |
619 | 0 | const char *name; |
620 | 0 | CK_RV rv; |
621 | |
|
622 | 0 | if (pInfo == NULL_PTR) |
623 | 0 | return CKR_ARGUMENTS_BAD; |
624 | | |
625 | 0 | rv = sc_pkcs11_lock(); |
626 | 0 | if (rv != CKR_OK) |
627 | 0 | return rv; |
628 | | |
629 | 0 | sc_log(context, "C_GetSlotInfo(0x%lx)", slotID); |
630 | |
|
631 | 0 | if (sc_pkcs11_conf.init_sloppy) { |
632 | | /* Most likely virtual_slots is empty and has not |
633 | | * been initialized because the caller has *not* called C_GetSlotList |
634 | | * before C_GetSlotInfo, as required by PKCS#11. Initialize |
635 | | * virtual_slots to make things work and hope the caller knows what |
636 | | * it's doing... */ |
637 | 0 | card_detect_all(); |
638 | 0 | } |
639 | |
|
640 | 0 | rv = slot_get_slot(slotID, &slot); |
641 | 0 | DEBUG_VSS(slot, "C_GetSlotInfo found"); |
642 | 0 | SC_LOG_RV("C_GetSlotInfo() get slot rv %s", rv); |
643 | 0 | if (rv == CKR_OK) { |
644 | 0 | if (slot->reader == NULL) { |
645 | 0 | rv = CKR_TOKEN_NOT_PRESENT; |
646 | 0 | } else { |
647 | 0 | now = get_current_time(); |
648 | 0 | if (now >= slot->slot_state_expires || now == 0) { |
649 | | /* Update slot status */ |
650 | 0 | rv = card_detect(slot->reader); |
651 | 0 | sc_log(context, "C_GetSlotInfo() card detect rv 0x%lX", rv); |
652 | |
|
653 | 0 | if (rv == CKR_TOKEN_NOT_RECOGNIZED || rv == CKR_OK) |
654 | 0 | slot->slot_info.flags |= CKF_TOKEN_PRESENT; |
655 | | |
656 | | /* Don't ask again within the next second */ |
657 | 0 | slot->slot_state_expires = now + 1000; |
658 | 0 | } |
659 | 0 | } |
660 | 0 | } |
661 | |
|
662 | 0 | if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED) |
663 | 0 | rv = CKR_OK; |
664 | |
|
665 | 0 | if (rv == CKR_OK) |
666 | 0 | memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO)); |
667 | |
|
668 | 0 | sc_log(context, "C_GetSlotInfo() flags 0x%lX", pInfo->flags); |
669 | |
|
670 | 0 | name = lookup_enum(RV_T, rv); |
671 | 0 | if (name) |
672 | 0 | sc_log(context, "C_GetSlotInfo(0x%lx) = %s", slotID, name); |
673 | 0 | else |
674 | 0 | sc_log(context, "C_GetSlotInfo(0x%lx) = 0x%08lX", slotID, rv); |
675 | 0 | sc_pkcs11_unlock(); |
676 | 0 | return rv; |
677 | 0 | } |
678 | | |
679 | | CK_RV C_GetMechanismList(CK_SLOT_ID slotID, |
680 | | CK_MECHANISM_TYPE_PTR pMechanismList, |
681 | | CK_ULONG_PTR pulCount) |
682 | 0 | { |
683 | 0 | struct sc_pkcs11_slot *slot; |
684 | 0 | CK_RV rv; |
685 | |
|
686 | 0 | if (pulCount == NULL_PTR) |
687 | 0 | return CKR_ARGUMENTS_BAD; |
688 | | |
689 | 0 | rv = sc_pkcs11_lock(); |
690 | 0 | if (rv != CKR_OK) |
691 | 0 | return rv; |
692 | | |
693 | 0 | rv = slot_get_token(slotID, &slot); |
694 | 0 | if (rv == CKR_OK) |
695 | 0 | rv = sc_pkcs11_get_mechanism_list(slot->p11card, pMechanismList, pulCount); |
696 | |
|
697 | 0 | sc_pkcs11_unlock(); |
698 | 0 | return rv; |
699 | 0 | } |
700 | | |
701 | | CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, |
702 | | CK_MECHANISM_TYPE type, |
703 | | CK_MECHANISM_INFO_PTR pInfo) |
704 | 0 | { |
705 | 0 | struct sc_pkcs11_slot *slot; |
706 | 0 | CK_RV rv; |
707 | |
|
708 | 0 | if (pInfo == NULL_PTR) |
709 | 0 | return CKR_ARGUMENTS_BAD; |
710 | | |
711 | 0 | rv = sc_pkcs11_lock(); |
712 | 0 | if (rv != CKR_OK) |
713 | 0 | return rv; |
714 | | |
715 | 0 | rv = slot_get_token(slotID, &slot); |
716 | 0 | if (rv == CKR_OK) |
717 | 0 | rv = sc_pkcs11_get_mechanism_info(slot->p11card, type, pInfo); |
718 | |
|
719 | 0 | sc_pkcs11_unlock(); |
720 | 0 | return rv; |
721 | 0 | } |
722 | | |
723 | | CK_RV C_InitToken(CK_SLOT_ID slotID, |
724 | | CK_CHAR_PTR pPin, |
725 | | CK_ULONG ulPinLen, |
726 | | CK_CHAR_PTR pLabel) |
727 | 271 | { |
728 | 271 | struct sc_pkcs11_session *session; |
729 | 271 | struct sc_pkcs11_slot *slot; |
730 | 271 | unsigned char *label, *cpo; |
731 | 271 | CK_RV rv; |
732 | 271 | unsigned int i; |
733 | | |
734 | | /* Strip trailing whitespace and null terminate the label. |
735 | | * Keep the fixed-length buffer though as some other layers or drivers (SC-HSM) |
736 | | * might expect the length is fixed! */ |
737 | 271 | label = malloc(33); |
738 | 271 | if (label == NULL) { |
739 | 0 | sc_log(context, "Failed to allocate label memory"); |
740 | 0 | return CKR_HOST_MEMORY; |
741 | 0 | } |
742 | 271 | memcpy(label, pLabel, 32); |
743 | 271 | label[32] = 0; |
744 | 271 | cpo = label + 31; |
745 | 8.30k | while ((cpo >= label) && (*cpo == ' ')) { |
746 | 8.03k | *cpo = 0; |
747 | 8.03k | cpo--; |
748 | 8.03k | } |
749 | | |
750 | 271 | sc_log(context, "C_InitToken(pLabel='%s') called", label); |
751 | 271 | rv = sc_pkcs11_lock(); |
752 | 271 | if (rv != CKR_OK) { |
753 | 0 | free(label); |
754 | 0 | return rv; |
755 | 0 | } |
756 | | |
757 | 271 | rv = slot_get_token(slotID, &slot); |
758 | 271 | if (rv != CKR_OK) { |
759 | 0 | sc_log(context, "C_InitToken() get token error 0x%lX", rv); |
760 | 0 | goto out; |
761 | 0 | } |
762 | | |
763 | 271 | if (!slot->p11card || !slot->p11card->framework |
764 | 271 | || !slot->p11card->framework->init_token) { |
765 | 0 | sc_log(context, "C_InitToken() not supported by framework"); |
766 | 0 | rv = CKR_FUNCTION_NOT_SUPPORTED; |
767 | 0 | goto out; |
768 | 0 | } |
769 | | |
770 | | /* Make sure there's no open session for this token */ |
771 | 271 | for (i=0; i<list_size(&sessions); i++) { |
772 | 271 | session = (struct sc_pkcs11_session*)list_get_at(&sessions, i); |
773 | 271 | if (session->slot == slot) { |
774 | 271 | rv = CKR_SESSION_EXISTS; |
775 | 271 | goto out; |
776 | 271 | } |
777 | 271 | } |
778 | | |
779 | 0 | rv = slot->p11card->framework->init_token(slot, slot->fw_data, pPin, ulPinLen, label); |
780 | 0 | if (rv == CKR_OK) { |
781 | | /* Now we should re-bind all tokens so they get the |
782 | | * corresponding function vector and flags */ |
783 | 0 | } |
784 | |
|
785 | 271 | out: |
786 | 271 | sc_pkcs11_unlock(); |
787 | 271 | sc_log(context, "C_InitToken(pLabel='%s') returns 0x%lX", label, rv); |
788 | 271 | free(label); |
789 | 271 | return rv; |
790 | 0 | } |
791 | | |
792 | | CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */ |
793 | | CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */ |
794 | | CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */ |
795 | 0 | { |
796 | 0 | sc_reader_t *found; |
797 | 0 | unsigned int mask, events; |
798 | 0 | void *reader_states = NULL; |
799 | 0 | CK_SLOT_ID slot_id; |
800 | 0 | CK_RV rv; |
801 | 0 | int r; |
802 | |
|
803 | 0 | if (pReserved != NULL_PTR) |
804 | 0 | return CKR_ARGUMENTS_BAD; |
805 | | |
806 | 0 | sc_log(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK)); |
807 | 0 | #ifndef PCSCLITE_GOOD |
808 | | /* Not all pcsc-lite versions implement consistently used functions as they are */ |
809 | 0 | if (!(flags & CKF_DONT_BLOCK)) |
810 | 0 | return CKR_FUNCTION_NOT_SUPPORTED; |
811 | 0 | #endif /* PCSCLITE_GOOD */ |
812 | 0 | rv = sc_pkcs11_lock(); |
813 | 0 | if (rv != CKR_OK) |
814 | 0 | return rv; |
815 | | |
816 | 0 | mask = SC_EVENT_CARD_EVENTS | SC_EVENT_READER_EVENTS; |
817 | | /* Detect and add new slots for added readers v2.20 */ |
818 | |
|
819 | 0 | rv = slot_find_changed(&slot_id, mask); |
820 | 0 | if ((rv == CKR_OK) || (flags & CKF_DONT_BLOCK)) |
821 | 0 | goto out; |
822 | | |
823 | 0 | again: |
824 | 0 | sc_log(context, "C_WaitForSlotEvent() reader_states:%p", reader_states); |
825 | 0 | sc_pkcs11_unlock(); |
826 | 0 | r = sc_wait_for_event(context, mask, &found, &events, -1, &reader_states); |
827 | | /* Was C_Finalize called ? */ |
828 | 0 | if (in_finalize == 1) |
829 | 0 | return CKR_CRYPTOKI_NOT_INITIALIZED; |
830 | | |
831 | 0 | if ((rv = sc_pkcs11_lock()) != CKR_OK) |
832 | 0 | return rv; |
833 | | |
834 | 0 | if (r != SC_SUCCESS) { |
835 | 0 | sc_log(context, "sc_wait_for_event() returned %d\n", r); |
836 | 0 | rv = sc_to_cryptoki_error(r, "C_WaitForSlotEvent"); |
837 | 0 | goto out; |
838 | 0 | } |
839 | | |
840 | | /* If no changed slot was found (maybe an unsupported card |
841 | | * was inserted/removed) then go waiting again */ |
842 | 0 | rv = slot_find_changed(&slot_id, mask); |
843 | 0 | if (rv != CKR_OK) |
844 | 0 | goto again; |
845 | | |
846 | 0 | out: |
847 | 0 | if (pSlot) |
848 | 0 | *pSlot = slot_id; |
849 | | |
850 | | /* Free allocated readers states holder */ |
851 | 0 | if (reader_states) { |
852 | 0 | sc_log(context, "free reader states"); |
853 | 0 | sc_wait_for_event(context, 0, NULL, NULL, -1, &reader_states); |
854 | 0 | } |
855 | |
|
856 | 0 | SC_LOG_RV("C_WaitForSlotEvent() = %s", rv); |
857 | 0 | sc_pkcs11_unlock(); |
858 | 0 | return rv; |
859 | 0 | } |
860 | | |
861 | | /* |
862 | | * Interfaces |
863 | | */ |
864 | 0 | #define NUM_INTERFACES 2 |
865 | 0 | #define DEFAULT_INTERFACE 0 |
866 | | // clang-format off |
867 | | CK_INTERFACE interfaces[NUM_INTERFACES] = { |
868 | | {"PKCS 11", (void *)&pkcs11_function_list_3_0, 0}, |
869 | | {"PKCS 11", (void *)&pkcs11_function_list, 0} |
870 | | }; |
871 | | // clang-format on |
872 | | |
873 | | CK_RV C_GetInterfaceList(CK_INTERFACE_PTR pInterfacesList, /* returned interfaces */ |
874 | | CK_ULONG_PTR pulCount) /* number of interfaces returned */ |
875 | 0 | { |
876 | 0 | sc_log(context, "C_GetInterfaceList()"); |
877 | |
|
878 | 0 | if (pulCount == NULL_PTR) |
879 | 0 | return CKR_ARGUMENTS_BAD; |
880 | | |
881 | 0 | if (pInterfacesList == NULL_PTR) { |
882 | 0 | *pulCount = NUM_INTERFACES; |
883 | 0 | sc_log(context, "was only a size inquiry (%lu)\n", *pulCount); |
884 | 0 | return CKR_OK; |
885 | 0 | } |
886 | | |
887 | 0 | if (*pulCount < NUM_INTERFACES) { |
888 | 0 | sc_log(context, "buffer was too small (needed %d)\n", NUM_INTERFACES); |
889 | 0 | *pulCount = NUM_INTERFACES; |
890 | 0 | return CKR_BUFFER_TOO_SMALL; |
891 | 0 | } |
892 | | |
893 | 0 | memcpy(pInterfacesList, interfaces, NUM_INTERFACES * sizeof(CK_INTERFACE)); |
894 | 0 | *pulCount = NUM_INTERFACES; |
895 | |
|
896 | 0 | sc_log(context, "returned %lu interfaces\n", *pulCount); |
897 | 0 | return CKR_OK; |
898 | 0 | } |
899 | | |
900 | | CK_RV C_GetInterface(CK_UTF8CHAR_PTR pInterfaceName, /* name of the interface */ |
901 | | CK_VERSION_PTR pVersion, /* version of the interface */ |
902 | | CK_INTERFACE_PTR_PTR ppInterface, /* returned interface */ |
903 | | CK_FLAGS flags) /* flags controlling the semantics |
904 | | * of the interface */ |
905 | 0 | { |
906 | 0 | int i; |
907 | |
|
908 | 0 | sc_log(context, "C_GetInterface(%s)", |
909 | 0 | pInterfaceName == NULL_PTR ? "<default>" : (char *)pInterfaceName); |
910 | |
|
911 | 0 | if (ppInterface == NULL) { |
912 | 0 | return CKR_ARGUMENTS_BAD; |
913 | 0 | } |
914 | | |
915 | 0 | if (pInterfaceName == NULL_PTR) { |
916 | | /* return default interface */ |
917 | 0 | *ppInterface = &interfaces[DEFAULT_INTERFACE]; |
918 | 0 | sc_log(context, "Returning default interface\n"); |
919 | 0 | return CKR_OK; |
920 | 0 | } |
921 | | |
922 | 0 | for (i = 0; i < NUM_INTERFACES; i++) { |
923 | 0 | CK_VERSION_PTR interface_version = (CK_VERSION_PTR)interfaces[i].pFunctionList; |
924 | | |
925 | | /* The interface name is not null here */ |
926 | 0 | if (strcmp((char *)pInterfaceName, interfaces[i].pInterfaceName) != 0) { |
927 | 0 | continue; |
928 | 0 | } |
929 | | /* If version is not null, it must match */ |
930 | 0 | if (pVersion != NULL_PTR && (pVersion->major != interface_version->major || |
931 | 0 | pVersion->minor != interface_version->minor)) { |
932 | 0 | continue; |
933 | 0 | } |
934 | | /* If any flags specified, it must be supported by the interface */ |
935 | 0 | if ((flags & interfaces[i].flags) != flags) { |
936 | 0 | continue; |
937 | 0 | } |
938 | 0 | *ppInterface = &interfaces[i]; |
939 | 0 | sc_log(context, "Returning interface %s\n", (*ppInterface)->pInterfaceName); |
940 | 0 | return CKR_OK; |
941 | 0 | } |
942 | 0 | sc_log(context, "Interface not found: %s, version=%d.%d, flags=%lu\n", |
943 | 0 | pInterfaceName ? (char *)pInterfaceName : "<null>", |
944 | 0 | pVersion ? (*pVersion).major : 0, |
945 | 0 | pVersion ? (*pVersion).minor : 0, |
946 | 0 | flags); |
947 | |
|
948 | 0 | return CKR_ARGUMENTS_BAD; |
949 | 0 | } |
950 | | |
951 | | /* |
952 | | * Locking functions |
953 | | */ |
954 | | |
955 | | CK_RV |
956 | | sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args) |
957 | 15.4k | { |
958 | 15.4k | CK_RV rv = CKR_OK; |
959 | | |
960 | 15.4k | int applock = 0; |
961 | 15.4k | int oslock = 0; |
962 | 15.4k | if (global_lock) |
963 | 0 | return CKR_OK; |
964 | | |
965 | | /* No CK_C_INITIALIZE_ARGS pointer, no locking */ |
966 | 15.4k | if (!args) |
967 | 15.4k | return CKR_OK; |
968 | | |
969 | 0 | if (args->pReserved != NULL_PTR) |
970 | 0 | return CKR_ARGUMENTS_BAD; |
971 | | |
972 | 0 | app_locking = *args; |
973 | | |
974 | | /* If the app tells us OS locking is okay, |
975 | | * use that. Otherwise use the supplied functions. |
976 | | */ |
977 | 0 | global_locking = NULL; |
978 | 0 | if (args->CreateMutex && args->DestroyMutex && |
979 | 0 | args->LockMutex && args->UnlockMutex) { |
980 | 0 | applock = 1; |
981 | 0 | } |
982 | 0 | if ((args->flags & CKF_OS_LOCKING_OK)) { |
983 | 0 | oslock = 1; |
984 | 0 | } |
985 | | |
986 | | /* Based on PKCS#11 v2.11 11.4 */ |
987 | 0 | if (applock && oslock) { |
988 | | /* Shall be used in threaded environment, prefer app provided locking */ |
989 | 0 | global_locking = &app_locking; |
990 | 0 | } else if (!applock && oslock) { |
991 | | /* Shall be used in threaded environment, must use operating system locking */ |
992 | 0 | global_locking = default_mutex_funcs; |
993 | 0 | } else if (applock && !oslock) { |
994 | | /* Shall be used in threaded environment, must use app provided locking */ |
995 | 0 | global_locking = &app_locking; |
996 | 0 | } else if (!applock && !oslock) { |
997 | | /* Shall not be used in threaded environment, use operating system locking */ |
998 | 0 | global_locking = default_mutex_funcs; |
999 | 0 | } |
1000 | |
|
1001 | 0 | if (global_locking != NULL) { |
1002 | | /* create mutex */ |
1003 | 0 | rv = global_locking->CreateMutex(&global_lock); |
1004 | 0 | } |
1005 | |
|
1006 | 0 | return rv; |
1007 | 0 | } |
1008 | | |
1009 | | CK_RV sc_pkcs11_lock(void) |
1010 | 55.1k | { |
1011 | 55.1k | if (context == NULL) |
1012 | 0 | return CKR_CRYPTOKI_NOT_INITIALIZED; |
1013 | | |
1014 | 55.1k | if (!global_lock) |
1015 | 55.1k | return CKR_OK; |
1016 | 0 | if (global_locking) { |
1017 | 0 | while (global_locking->LockMutex(global_lock) != CKR_OK) |
1018 | 0 | ; |
1019 | 0 | } |
1020 | |
|
1021 | 0 | return CKR_OK; |
1022 | 55.1k | } |
1023 | | |
1024 | | static void |
1025 | | __sc_pkcs11_unlock(void *lock) |
1026 | 39.6k | { |
1027 | 39.6k | if (!lock) |
1028 | 39.6k | return; |
1029 | 0 | if (global_locking) { |
1030 | 0 | while (global_locking->UnlockMutex(lock) != CKR_OK) |
1031 | 0 | ; |
1032 | 0 | } |
1033 | 0 | } |
1034 | | |
1035 | | void sc_pkcs11_unlock(void) |
1036 | 39.6k | { |
1037 | 39.6k | __sc_pkcs11_unlock(global_lock); |
1038 | 39.6k | } |
1039 | | |
1040 | | /* |
1041 | | * Free the lock - note the lock must be held when |
1042 | | * you come here |
1043 | | */ |
1044 | | void sc_pkcs11_free_lock(void) |
1045 | 15.4k | { |
1046 | 15.4k | void *tempLock; |
1047 | | |
1048 | 15.4k | if (!(tempLock = global_lock)) |
1049 | 15.4k | return; |
1050 | | |
1051 | | /* Clear the global lock pointer - once we've |
1052 | | * unlocked the mutex it's as good as gone */ |
1053 | 0 | global_lock = NULL; |
1054 | | |
1055 | | /* Now unlock. On SMP machines the synchronization |
1056 | | * primitives should take care of flushing out |
1057 | | * all changed data to RAM */ |
1058 | 0 | __sc_pkcs11_unlock(tempLock); |
1059 | |
|
1060 | 0 | if (global_locking) |
1061 | 0 | global_locking->DestroyMutex(tempLock); |
1062 | 0 | global_locking = NULL; |
1063 | 0 | } |
1064 | | |
1065 | | CK_FUNCTION_LIST pkcs11_function_list = { |
1066 | | { 2, 20 }, /* Note: NSS/Firefox ignores this version number and uses C_GetInfo() */ |
1067 | | C_Initialize, |
1068 | | C_Finalize, |
1069 | | C_GetInfoV2, |
1070 | | C_GetFunctionList, |
1071 | | C_GetSlotList, |
1072 | | C_GetSlotInfo, |
1073 | | C_GetTokenInfo, |
1074 | | C_GetMechanismList, |
1075 | | C_GetMechanismInfo, |
1076 | | C_InitToken, |
1077 | | C_InitPIN, |
1078 | | C_SetPIN, |
1079 | | C_OpenSession, |
1080 | | C_CloseSession, |
1081 | | C_CloseAllSessions, |
1082 | | C_GetSessionInfo, |
1083 | | C_GetOperationState, |
1084 | | C_SetOperationState, |
1085 | | C_Login, |
1086 | | C_Logout, |
1087 | | C_CreateObject, |
1088 | | C_CopyObject, |
1089 | | C_DestroyObject, |
1090 | | C_GetObjectSize, |
1091 | | C_GetAttributeValue, |
1092 | | C_SetAttributeValue, |
1093 | | C_FindObjectsInit, |
1094 | | C_FindObjects, |
1095 | | C_FindObjectsFinal, |
1096 | | C_EncryptInit, |
1097 | | C_Encrypt, |
1098 | | C_EncryptUpdate, |
1099 | | C_EncryptFinal, |
1100 | | C_DecryptInit, |
1101 | | C_Decrypt, |
1102 | | C_DecryptUpdate, |
1103 | | C_DecryptFinal, |
1104 | | C_DigestInit, |
1105 | | C_Digest, |
1106 | | C_DigestUpdate, |
1107 | | C_DigestKey, |
1108 | | C_DigestFinal, |
1109 | | C_SignInit, |
1110 | | C_Sign, |
1111 | | C_SignUpdate, |
1112 | | C_SignFinal, |
1113 | | C_SignRecoverInit, |
1114 | | C_SignRecover, |
1115 | | C_VerifyInit, |
1116 | | C_Verify, |
1117 | | C_VerifyUpdate, |
1118 | | C_VerifyFinal, |
1119 | | C_VerifyRecoverInit, |
1120 | | C_VerifyRecover, |
1121 | | C_DigestEncryptUpdate, |
1122 | | C_DecryptDigestUpdate, |
1123 | | C_SignEncryptUpdate, |
1124 | | C_DecryptVerifyUpdate, |
1125 | | C_GenerateKey, |
1126 | | C_GenerateKeyPair, |
1127 | | C_WrapKey, |
1128 | | C_UnwrapKey, |
1129 | | C_DeriveKey, |
1130 | | C_SeedRandom, |
1131 | | C_GenerateRandom, |
1132 | | C_GetFunctionStatus, |
1133 | | C_CancelFunction, |
1134 | | C_WaitForSlotEvent |
1135 | | }; |
1136 | | |
1137 | | /* Returned from getInterface */ |
1138 | | CK_FUNCTION_LIST_3_0 pkcs11_function_list_3_0 = { |
1139 | | { 3, 0 }, |
1140 | | C_Initialize, |
1141 | | C_Finalize, |
1142 | | C_GetInfo, |
1143 | | C_GetFunctionList, |
1144 | | C_GetSlotList, |
1145 | | C_GetSlotInfo, |
1146 | | C_GetTokenInfo, |
1147 | | C_GetMechanismList, |
1148 | | C_GetMechanismInfo, |
1149 | | C_InitToken, |
1150 | | C_InitPIN, |
1151 | | C_SetPIN, |
1152 | | C_OpenSession, |
1153 | | C_CloseSession, |
1154 | | C_CloseAllSessions, |
1155 | | C_GetSessionInfo, |
1156 | | C_GetOperationState, |
1157 | | C_SetOperationState, |
1158 | | C_Login, |
1159 | | C_Logout, |
1160 | | C_CreateObject, |
1161 | | C_CopyObject, |
1162 | | C_DestroyObject, |
1163 | | C_GetObjectSize, |
1164 | | C_GetAttributeValue, |
1165 | | C_SetAttributeValue, |
1166 | | C_FindObjectsInit, |
1167 | | C_FindObjects, |
1168 | | C_FindObjectsFinal, |
1169 | | C_EncryptInit, |
1170 | | C_Encrypt, |
1171 | | C_EncryptUpdate, |
1172 | | C_EncryptFinal, |
1173 | | C_DecryptInit, |
1174 | | C_Decrypt, |
1175 | | C_DecryptUpdate, |
1176 | | C_DecryptFinal, |
1177 | | C_DigestInit, |
1178 | | C_Digest, |
1179 | | C_DigestUpdate, |
1180 | | C_DigestKey, |
1181 | | C_DigestFinal, |
1182 | | C_SignInit, |
1183 | | C_Sign, |
1184 | | C_SignUpdate, |
1185 | | C_SignFinal, |
1186 | | C_SignRecoverInit, |
1187 | | C_SignRecover, |
1188 | | C_VerifyInit, |
1189 | | C_Verify, |
1190 | | C_VerifyUpdate, |
1191 | | C_VerifyFinal, |
1192 | | C_VerifyRecoverInit, |
1193 | | C_VerifyRecover, |
1194 | | C_DigestEncryptUpdate, |
1195 | | C_DecryptDigestUpdate, |
1196 | | C_SignEncryptUpdate, |
1197 | | C_DecryptVerifyUpdate, |
1198 | | C_GenerateKey, |
1199 | | C_GenerateKeyPair, |
1200 | | C_WrapKey, |
1201 | | C_UnwrapKey, |
1202 | | C_DeriveKey, |
1203 | | C_SeedRandom, |
1204 | | C_GenerateRandom, |
1205 | | C_GetFunctionStatus, |
1206 | | C_CancelFunction, |
1207 | | C_WaitForSlotEvent, |
1208 | | C_GetInterfaceList, |
1209 | | C_GetInterface, |
1210 | | C_LoginUser, |
1211 | | C_SessionCancel, |
1212 | | C_MessageEncryptInit, |
1213 | | C_EncryptMessage, |
1214 | | C_EncryptMessageBegin, |
1215 | | C_EncryptMessageNext, |
1216 | | C_MessageEncryptFinal, |
1217 | | C_MessageDecryptInit, |
1218 | | C_DecryptMessage, |
1219 | | C_DecryptMessageBegin, |
1220 | | C_DecryptMessageNext, |
1221 | | C_MessageDecryptFinal, |
1222 | | C_MessageSignInit, |
1223 | | C_SignMessage, |
1224 | | C_SignMessageBegin, |
1225 | | C_SignMessageNext, |
1226 | | C_MessageSignFinal, |
1227 | | C_MessageVerifyInit, |
1228 | | C_VerifyMessage, |
1229 | | C_VerifyMessageBegin, |
1230 | | C_VerifyMessageNext, |
1231 | | C_MessageVerifyFinal |
1232 | | }; |