pkcs11General.c revision 7574:e19e13b485fa
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"@(#)pkcs11General.c	1.10	08/08/12 SMI"
27
28#include <unistd.h>
29#include <string.h>
30#include <cryptoutil.h>
31#include <pthread.h>
32
33#include <security/cryptoki.h>
34#include "pkcs11Global.h"
35#include "pkcs11Slot.h"
36#include "pkcs11Conf.h"
37#include "pkcs11Session.h"
38#include "metaGlobal.h"
39
40#pragma fini(pkcs11_fini)
41
42static struct CK_FUNCTION_LIST functionList = {
43	{ 2, 20 },	/* version */
44	C_Initialize,
45	C_Finalize,
46	C_GetInfo,
47	C_GetFunctionList,
48	C_GetSlotList,
49	C_GetSlotInfo,
50	C_GetTokenInfo,
51	C_GetMechanismList,
52	C_GetMechanismInfo,
53	C_InitToken,
54	C_InitPIN,
55	C_SetPIN,
56	C_OpenSession,
57	C_CloseSession,
58	C_CloseAllSessions,
59	C_GetSessionInfo,
60	C_GetOperationState,
61	C_SetOperationState,
62	C_Login,
63	C_Logout,
64	C_CreateObject,
65	C_CopyObject,
66	C_DestroyObject,
67	C_GetObjectSize,
68	C_GetAttributeValue,
69	C_SetAttributeValue,
70	C_FindObjectsInit,
71	C_FindObjects,
72	C_FindObjectsFinal,
73	C_EncryptInit,
74	C_Encrypt,
75	C_EncryptUpdate,
76	C_EncryptFinal,
77	C_DecryptInit,
78	C_Decrypt,
79	C_DecryptUpdate,
80	C_DecryptFinal,
81	C_DigestInit,
82	C_Digest,
83	C_DigestUpdate,
84	C_DigestKey,
85	C_DigestFinal,
86	C_SignInit,
87	C_Sign,
88	C_SignUpdate,
89	C_SignFinal,
90	C_SignRecoverInit,
91	C_SignRecover,
92	C_VerifyInit,
93	C_Verify,
94	C_VerifyUpdate,
95	C_VerifyFinal,
96	C_VerifyRecoverInit,
97	C_VerifyRecover,
98	C_DigestEncryptUpdate,
99	C_DecryptDigestUpdate,
100	C_SignEncryptUpdate,
101	C_DecryptVerifyUpdate,
102	C_GenerateKey,
103	C_GenerateKeyPair,
104	C_WrapKey,
105	C_UnwrapKey,
106	C_DeriveKey,
107	C_SeedRandom,
108	C_GenerateRandom,
109	C_GetFunctionStatus,
110	C_CancelFunction,
111	C_WaitForSlotEvent
112};
113
114boolean_t pkcs11_initialized = B_FALSE;
115boolean_t pkcs11_cant_create_threads = B_FALSE;
116boolean_t fini_called = B_FALSE;
117static boolean_t pkcs11_atfork_initialized = B_FALSE;
118static pid_t pkcs11_pid = 0;
119
120/* protects pkcs11_[initialized|pid], and fastpath */
121static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER;
122
123static CK_RV finalize_common(CK_VOID_PTR pReserved);
124static void pkcs11_fini();
125
126/*
127 * Ensure that before a fork, all mutexes are taken.
128 * Order:
129 * 1. globalmutex
130 * 2. slottable->st_mutex
131 * 3. all slottable->st_slots' mutexes
132 */
133static void
134pkcs11_fork_prepare(void)
135{
136	int i;
137	(void) pthread_mutex_lock(&globalmutex);
138	if (slottable != NULL) {
139		(void) pthread_mutex_lock(&slottable->st_mutex);
140
141		/* Take the sl_mutex of all slots */
142		for (i = slottable->st_first; i <= slottable->st_last; i++) {
143			if (slottable->st_slots[i] != NULL) {
144				(void) pthread_mutex_lock(
145				    &slottable->st_slots[i]->sl_mutex);
146			}
147		}
148	}
149}
150
151
152/*
153 * Ensure that after a fork, in the parent, all mutexes are released in opposite
154 * order to pkcs11_fork_prepare().
155 */
156static void
157pkcs11_fork_parent(void)
158{
159	int i;
160	if (slottable != NULL) {
161		/* Release the sl_mutex of all slots */
162		for (i = slottable->st_first; i <= slottable->st_last; i++) {
163			if (slottable->st_slots[i] != NULL) {
164				(void) pthread_mutex_unlock(
165				    &slottable->st_slots[i]->sl_mutex);
166			}
167		}
168		(void) pthread_mutex_unlock(&slottable->st_mutex);
169	}
170	(void) pthread_mutex_unlock(&globalmutex);
171}
172
173
174/*
175 * Ensure that after a fork, in the child, all mutexes are released in opposite
176 * order to pkcs11_fork_prepare() and cleanup is done.
177 */
178static void
179pkcs11_fork_child(void)
180{
181	int i;
182	if (slottable != NULL) {
183		/* Release the sl_mutex of all slots */
184		for (i = slottable->st_first; i <= slottable->st_last; i++) {
185			if (slottable->st_slots[i] != NULL) {
186				(void) pthread_mutex_unlock(
187				    &slottable->st_slots[i]->sl_mutex);
188			}
189		}
190		(void) pthread_mutex_unlock(&slottable->st_mutex);
191	}
192	(void) pthread_mutex_unlock(&globalmutex);
193	pkcs11_fini();
194}
195
196CK_RV
197C_Initialize(CK_VOID_PTR pInitArgs)
198{
199	CK_RV rv;
200	uentrylist_t *pliblist = NULL;
201	int initialize_pid;
202
203	/*
204	 * Grab lock to insure only one thread enters
205	 * this function at a time.
206	 */
207	(void) pthread_mutex_lock(&globalmutex);
208
209	initialize_pid = getpid();
210
211	/* Make sure function hasn't been called twice */
212	if (pkcs11_initialized) {
213		if (initialize_pid == pkcs11_pid) {
214			(void) pthread_mutex_unlock(&globalmutex);
215			return (CKR_CRYPTOKI_ALREADY_INITIALIZED);
216		} else {
217			/*
218			 * A fork has happened and the child is
219			 * reinitializing.  Do a finalize_common() to close
220			 * out any state from the parent, and then
221			 * continue on.
222			 */
223			(void) finalize_common(NULL);
224		}
225	}
226
227	/* Check if application has provided mutex-handling functions */
228	if (pInitArgs != NULL) {
229		CK_C_INITIALIZE_ARGS_PTR initargs =
230		    (CK_C_INITIALIZE_ARGS_PTR) pInitArgs;
231
232		/* pReserved should not be set */
233		if (initargs->pReserved != NULL) {
234			rv = CKR_ARGUMENTS_BAD;
235			goto errorexit;
236		}
237
238		/*
239		 * Make sure function pointers are either all NULL or
240		 * all set.
241		 */
242		if (!(((initargs->CreateMutex   != NULL) &&
243		    (initargs->LockMutex    != NULL) &&
244		    (initargs->UnlockMutex  != NULL) &&
245		    (initargs->DestroyMutex != NULL)) ||
246		    ((initargs->CreateMutex == NULL) &&
247		    (initargs->LockMutex    == NULL) &&
248		    (initargs->UnlockMutex  == NULL) &&
249		    (initargs->DestroyMutex == NULL)))) {
250			rv = CKR_ARGUMENTS_BAD;
251			goto errorexit;
252		}
253
254		if (!(initargs->flags & CKF_OS_LOCKING_OK)) {
255			if (initargs->CreateMutex != NULL) {
256				/*
257				 * Do not accept application supplied
258				 * locking primitives.
259				 */
260				rv = CKR_CANT_LOCK;
261				goto errorexit;
262			}
263
264		}
265		if (initargs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
266			/*
267			 * Calling application does not want the library
268			 * to create threads.  This will effect
269			 * C_WaitForSlotEvent().
270			 */
271			pkcs11_cant_create_threads = B_TRUE;
272		}
273	}
274
275	/* Initialize slot table */
276	rv = pkcs11_slottable_initialize();
277
278	if (rv != CKR_OK)
279		goto errorexit;
280
281	/* Get the list of providers */
282	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
283		rv = CKR_FUNCTION_FAILED;
284		goto errorexit;
285	}
286
287	/*
288	 * Load each provider, check for accessible slots,
289	 * and populate slottable.  If metaslot is enabled,
290	 * it will be initialized as well.
291	 */
292	rv = pkcs11_slot_mapping(pliblist, pInitArgs);
293
294	if (rv != CKR_OK)
295		goto errorexit;
296
297	pkcs11_initialized = B_TRUE;
298	pkcs11_pid = initialize_pid;
299	/* Children inherit parent's atfork handlers */
300	if (!pkcs11_atfork_initialized) {
301		(void) pthread_atfork(pkcs11_fork_prepare,
302		    pkcs11_fork_parent, pkcs11_fork_child);
303		pkcs11_atfork_initialized = B_TRUE;
304	}
305	(void) pthread_mutex_unlock(&globalmutex);
306
307	/* Cleanup data structures no longer needed */
308	free_uentrylist(pliblist);
309
310	return (CKR_OK);
311
312errorexit:
313	/* Cleanup any data structures that have already been allocated */
314	if (slottable)
315		(void) pkcs11_slottable_delete();
316	if (pliblist)
317		(void) free_uentrylist(pliblist);
318
319	(void) pthread_mutex_unlock(&globalmutex);
320	return (rv);
321
322}
323
324/*
325 * C_Finalize is a wrapper around finalize_common. The
326 * globalmutex should be locked by C_Finalize().
327 *
328 * When an explicit C_Finalize() call is received, all
329 * plugins currently in the slottable will also be
330 * finalized.  This must occur, even if libpkcs11(3lib)
331 * was not the first one to initialize the plugins, since it
332 * is the only way in PKCS#11 to force a refresh of the
333 * slot listings (ie to get new hardware devices).
334 */
335CK_RV
336C_Finalize(CK_VOID_PTR pReserved)
337{
338
339	CK_RV rv;
340
341	(void) pthread_mutex_lock(&globalmutex);
342
343	rv = finalize_common(pReserved);
344
345	(void) pthread_mutex_unlock(&globalmutex);
346
347	return (rv);
348}
349
350/*
351 * finalize_common() does the work for C_Finalize.  globalmutex
352 * must be held before calling this function.
353 */
354static CK_RV
355finalize_common(CK_VOID_PTR pReserved)
356{
357
358	CK_RV rv;
359
360	if (!pkcs11_initialized) {
361		return (CKR_CRYPTOKI_NOT_INITIALIZED);
362	}
363
364	if (pReserved != NULL) {
365		return (CKR_ARGUMENTS_BAD);
366	}
367
368	purefastpath = B_FALSE;
369	policyfastpath = B_FALSE;
370	fast_funcs = NULL;
371	fast_slot = 0;
372	pkcs11_initialized = B_FALSE;
373	pkcs11_cant_create_threads = B_FALSE;
374	pkcs11_pid = 0;
375
376	/* Check if C_WaitForSlotEvent() is currently active */
377	(void) pthread_mutex_lock(&slottable->st_mutex);
378	if (slottable->st_wfse_active) {
379		/*
380		 * Wait for this thread to proceed far enough to block or
381		 * end on its own.  Otherwise, teardown of slottable may
382		 * occurr before this active function completes.
383		 */
384		while (slottable->st_wfse_active) {
385			/*
386			 * If C_WaitForSlotEvent is blocking, wake it up and
387			 * return error to calling application.
388			 */
389			if (slottable->st_blocking) {
390				slottable->st_list_signaled = B_TRUE;
391				(void) pthread_cond_signal(
392				    &slottable->st_wait_cond);
393				(void) pthread_mutex_unlock(
394				    &slottable->st_mutex);
395				(void) pthread_join(slottable->st_tid, NULL);
396			}
397		}
398	} else {
399		(void) pthread_mutex_unlock(&slottable->st_mutex);
400	}
401
402	rv = pkcs11_slottable_delete();
403
404	return (rv);
405}
406
407/*
408 * pkcs11_fini() function required to make sure complete cleanup
409 * is done of plugins if the framework is ever unloaded without
410 * a C_Finalize() call.  This would be common when applications
411 * load and unload other libraries that use libpkcs11(3lib), since
412 * shared libraries should not call C_Finalize().
413 *
414 * If pkcs11_fini() is used, we set fini_called to B_TRUE so that
415 * pkcs11_slottable_delete() will not call C_Finalize() on the plugins.
416 *
417 * This is to protect in cases where the application has dlopened
418 * an object (for example, dlobj) that links to libpkcs11(3lib), but
419 * the application is unaware that the object is doing PKCS#11 calls
420 * underneath.  This application may later directly dlopen one of the
421 * plugins (like pkcs11_softtoken.so, or any other 3rd party provided
422 * plugin) in order to directly perform PKCS#11 operations.
423 *
424 * While it is still actively using the PKCS#11 plugin directly,
425 * the application may finish with dlobj and dlclose it.  As the
426 * reference count for libpkcs11(3lib) has become 0, pkcs11_fini()
427 * will be run by the linker.  Even though libpkcs11(3lib) was the
428 * first to initialize the plugin in this case, it is not safe for
429 * libpkcs11(3lib) to finalize the plugin, as the application would
430 * lose state.
431 */
432static void
433pkcs11_fini()
434{
435	(void) pthread_mutex_lock(&globalmutex);
436
437	/* if we're not initilized, do not attempt to finalize */
438	if (!pkcs11_initialized) {
439		(void) pthread_mutex_unlock(&globalmutex);
440		return;
441	}
442
443	fini_called = B_TRUE;
444
445	(void) finalize_common(NULL_PTR);
446
447	(void) pthread_mutex_unlock(&globalmutex);
448
449}
450
451CK_RV
452C_GetInfo(CK_INFO_PTR pInfo)
453{
454
455	/* Check for a fastpath */
456	if (purefastpath || policyfastpath) {
457		return (fast_funcs->C_GetInfo(pInfo));
458	}
459
460	if (!pkcs11_initialized)
461		return (CKR_CRYPTOKI_NOT_INITIALIZED);
462
463	if (pInfo == NULL) {
464		return (CKR_ARGUMENTS_BAD);
465	}
466
467	/*
468	 * Copy data into the provided buffer, use strncpy() instead
469	 * of strlcpy() so that the strings are NOT NULL terminated,
470	 * as required by the PKCS#11 standard
471	 */
472	(void) strncpy((char *)pInfo->manufacturerID, MANUFACTURER_ID,
473	    PKCS11_STRING_LENGTH);
474	(void) strncpy((char *)pInfo->libraryDescription,
475	    LIBRARY_DESCRIPTION, PKCS11_STRING_LENGTH);
476
477	pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
478	pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
479	pInfo->flags = 0;
480	pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR;
481	pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR;
482
483	return (CKR_OK);
484}
485
486/*
487 * This function is unaffected by the fast-path, since it is likely
488 * called before C_Initialize is, so we will not yet know the status
489 * of the fast-path.  Additionally, policy will still need to be
490 * enforced if applicable.
491 */
492CK_RV
493C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
494{
495	if (ppFunctionList == NULL) {
496		return (CKR_ARGUMENTS_BAD);
497	}
498
499	*ppFunctionList = &functionList;
500
501	return (CKR_OK);
502}
503
504
505/*
506 * This function is no longer supported in this revision of the PKCS#11
507 * standard.  It is maintained for backwards compatibility only.
508 */
509/*ARGSUSED*/
510CK_RV
511C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
512{
513	return (CKR_FUNCTION_NOT_PARALLEL);
514}
515
516
517/*
518 * This function is no longer supported in this revision of the PKCS#11
519 * standard.  It is maintained for backwards compatibility only.
520 */
521/*ARGSUSED*/
522CK_RV
523C_CancelFunction(CK_SESSION_HANDLE hSession)
524{
525	return (CKR_FUNCTION_NOT_PARALLEL);
526}
527