xref: /illumos-gate/usr/src/lib/pkcs11/libpkcs11/common/pkcs11General.c (revision 8b80e8cb6855118d46f605e91b5ed4ce83417395)
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 
42 static 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 
114 boolean_t pkcs11_initialized = B_FALSE;
115 boolean_t pkcs11_cant_create_threads = B_FALSE;
116 boolean_t fini_called = B_FALSE;
117 static boolean_t pkcs11_atfork_initialized = B_FALSE;
118 static pid_t pkcs11_pid = 0;
119 
120 /* protects pkcs11_[initialized|pid], and fastpath */
121 static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER;
122 
123 static CK_RV finalize_common(CK_VOID_PTR pReserved);
124 static 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  */
133 static void
134 pkcs11_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  */
156 static void
157 pkcs11_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  */
178 static void
179 pkcs11_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 
196 CK_RV
197 C_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 
312 errorexit:
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  */
335 CK_RV
336 C_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  */
354 static CK_RV
355 finalize_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  */
432 static void
433 pkcs11_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 
451 CK_RV
452 C_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  */
492 CK_RV
493 C_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*/
510 CK_RV
511 C_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*/
522 CK_RV
523 C_CancelFunction(CK_SESSION_HANDLE hSession)
524 {
525 	return (CKR_FUNCTION_NOT_PARALLEL);
526 }
527