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