xref: /illumos-gate/usr/src/lib/pkcs11/libpkcs11/common/pkcs11General.c (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <unistd.h>
30 #include <string.h>
31 #include <cryptoutil.h>
32 #include <pthread.h>
33 
34 #include <security/cryptoki.h>
35 #include "pkcs11Global.h"
36 #include "pkcs11Slot.h"
37 #include "pkcs11Conf.h"
38 #include "pkcs11Session.h"
39 
40 #pragma fini(pkcs11_fini)
41 
42 static struct CK_FUNCTION_LIST functionList = {
43 	{ 2, 11 },	/* 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 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, globalmutex is taken.
127  */
128 static void
129 pkcs11_fork_prepare(void)
130 {
131 	(void) pthread_mutex_lock(&globalmutex);
132 }
133 
134 
135 /*
136  * Ensure that after a fork, in the parent, globalmutex is released.
137  */
138 static void
139 pkcs11_fork_parent(void)
140 {
141 	(void) pthread_mutex_unlock(&globalmutex);
142 }
143 
144 
145 /*
146  * Ensure that after a fork, in the child, globalmutex is released
147  * and cleanup is done.
148  */
149 static void
150 pkcs11_fork_child(void)
151 {
152 	(void) pthread_mutex_unlock(&globalmutex);
153 	pkcs11_fini();
154 }
155 
156 CK_RV
157 C_Initialize(CK_VOID_PTR pInitArgs)
158 {
159 	CK_RV rv;
160 	uentrylist_t *pliblist = NULL;
161 	int initialize_pid;
162 
163 	/*
164 	 * Grab lock to insure only one thread enters
165 	 * this function at a time.
166 	 */
167 	(void) pthread_mutex_lock(&globalmutex);
168 
169 	initialize_pid = getpid();
170 
171 	/* Make sure function hasn't been called twice */
172 	if (pkcs11_initialized) {
173 		if (initialize_pid == pkcs11_pid) {
174 			(void) pthread_mutex_unlock(&globalmutex);
175 			return (CKR_CRYPTOKI_ALREADY_INITIALIZED);
176 		} else {
177 			/*
178 			 * A fork has happened and the child is
179 			 * reinitializing.  Do a finalize_common() to close
180 			 * out any state from the parent, and then
181 			 * continue on.
182 			 */
183 			(void) finalize_common(NULL);
184 		}
185 	}
186 
187 	/* Check if application has provided mutex-handling functions */
188 	if (pInitArgs != NULL) {
189 		CK_C_INITIALIZE_ARGS_PTR initargs =
190 			(CK_C_INITIALIZE_ARGS_PTR) pInitArgs;
191 
192 		/* pReserved should not be set */
193 		if (initargs->pReserved != NULL) {
194 			rv = CKR_ARGUMENTS_BAD;
195 			goto errorexit;
196 		}
197 
198 		/*
199 		 * Make sure function pointers are either all NULL or
200 		 * all set.
201 		 */
202 		if (!(((initargs->CreateMutex   != NULL) &&
203 			(initargs->LockMutex    != NULL) &&
204 			(initargs->UnlockMutex  != NULL) &&
205 			(initargs->DestroyMutex != NULL)) ||
206 			((initargs->CreateMutex == NULL) &&
207 			(initargs->LockMutex    == NULL) &&
208 			(initargs->UnlockMutex  == NULL) &&
209 			(initargs->DestroyMutex == NULL)))) {
210 			rv = CKR_ARGUMENTS_BAD;
211 			goto errorexit;
212 		}
213 
214 		if (!(initargs->flags & CKF_OS_LOCKING_OK)) {
215 			if (initargs->CreateMutex != NULL) {
216 				/*
217 				 * Do not accept application supplied
218 				 * locking primitives.
219 				 */
220 				rv = CKR_CANT_LOCK;
221 				goto errorexit;
222 			}
223 
224 		}
225 		if (initargs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
226 			/*
227 			 * Calling application does not want the library
228 			 * to create threads.  This will effect
229 			 * C_WaitForSlotEvent().
230 			 */
231 			pkcs11_cant_create_threads = B_TRUE;
232 		}
233 	}
234 
235 	/* Initialize slot table */
236 	rv = pkcs11_slottable_initialize();
237 
238 	if (rv != CKR_OK)
239 		goto errorexit;
240 
241 	/* Get the list of providers */
242 	if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
243 		rv = CKR_FUNCTION_FAILED;
244 		goto errorexit;
245 	}
246 
247 	/*
248 	 * Load each provider, check for accessible slots,
249 	 * and populate slottable.  If metaslot is enabled,
250 	 * it will be initialized as well.
251 	 */
252 	rv = pkcs11_slot_mapping(pliblist, pInitArgs);
253 
254 	if (rv != CKR_OK)
255 		goto errorexit;
256 
257 	pkcs11_initialized = B_TRUE;
258 	pkcs11_pid = initialize_pid;
259 	(void) pthread_atfork(pkcs11_fork_prepare,
260 	    pkcs11_fork_parent, pkcs11_fork_child);
261 	(void) pthread_mutex_unlock(&globalmutex);
262 
263 	/* Cleanup data structures no longer needed */
264 	free_uentrylist(pliblist);
265 
266 	return (CKR_OK);
267 
268 errorexit:
269 	/* Cleanup any data structures that have already been allocated */
270 	if (slottable)
271 		(void) pkcs11_slottable_delete();
272 	if (pliblist)
273 		(void) free_uentrylist(pliblist);
274 
275 	(void) pthread_mutex_unlock(&globalmutex);
276 	return (rv);
277 
278 }
279 
280 /*
281  * C_Finalize is a wrapper around finalize_common. The
282  * globalmutex should be locked by C_Finalize().
283  *
284  * When an explicit C_Finalize() call is received, all
285  * plugins currently in the slottable will also be
286  * finalized.  This must occur, even if libpkcs11(3lib)
287  * was not the first one to initialize the plugins, since it
288  * is the only way in PKCS#11 to force a refresh of the
289  * slot listings (ie to get new hardware devices).
290  */
291 CK_RV
292 C_Finalize(CK_VOID_PTR pReserved)
293 {
294 
295 	CK_RV rv;
296 
297 	(void) pthread_mutex_lock(&globalmutex);
298 
299 	rv = finalize_common(pReserved);
300 
301 	(void) pthread_mutex_unlock(&globalmutex);
302 
303 	return (rv);
304 }
305 
306 /*
307  * finalize_common() does the work for C_Finalize.  globalmutex
308  * must be held before calling this function.
309  */
310 static CK_RV
311 finalize_common(CK_VOID_PTR pReserved)
312 {
313 
314 	CK_RV rv;
315 
316 	if (!pkcs11_initialized) {
317 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
318 	}
319 
320 	if (pReserved != NULL) {
321 		return (CKR_ARGUMENTS_BAD);
322 	}
323 
324 	purefastpath = B_FALSE;
325 	policyfastpath = B_FALSE;
326 	fast_funcs = NULL;
327 	fast_slot = 0;
328 	pkcs11_initialized = B_FALSE;
329 	pkcs11_cant_create_threads = B_FALSE;
330 	pkcs11_pid = 0;
331 
332 	/* Check if C_WaitForSlotEvent() is currently active */
333 	(void) pthread_mutex_lock(&slottable->st_mutex);
334 	if (slottable->st_wfse_active) {
335 		/*
336 		 * Wait for this thread to proceed far enough to block or
337 		 * end on its own.  Otherwise, teardown of slottable may
338 		 * occurr before this active function completes.
339 		 */
340 		while (slottable->st_wfse_active) {
341 			/*
342 			 * If C_WaitForSlotEvent is blocking, wake it up and
343 			 * return error to calling application.
344 			 */
345 			if (slottable->st_blocking) {
346 				slottable->st_list_signaled = B_TRUE;
347 				(void) pthread_cond_signal(
348 					&slottable->st_wait_cond);
349 				(void) pthread_mutex_unlock(
350 					&slottable->st_mutex);
351 				(void) pthread_join(slottable->st_tid, NULL);
352 			}
353 		}
354 	} else {
355 		(void) pthread_mutex_unlock(&slottable->st_mutex);
356 	}
357 
358 	rv = pkcs11_slottable_delete();
359 
360 	return (rv);
361 }
362 
363 /*
364  * pkcs11_fini() function required to make sure complete cleanup
365  * is done of plugins if the framework is ever unloaded without
366  * a C_Finalize() call.  This would be common when applications
367  * load and unload other libraries that use libpkcs11(3lib), since
368  * shared libraries should not call C_Finalize().
369  *
370  * If pkcs11_fini() is used, we set fini_called to B_TRUE so that
371  * pkcs11_slottable_delete() will not call C_Finalize() on the plugins.
372  *
373  * This is to protect in cases where the application has dlopened
374  * an object (for example, dlobj) that links to libpkcs11(3lib), but
375  * the application is unaware that the object is doing PKCS#11 calls
376  * underneath.  This application may later directly dlopen one of the
377  * plugins (like pkcs11_softtoken.so, or any other 3rd party provided
378  * plugin) in order to directly perform PKCS#11 operations.
379  *
380  * While it is still actively using the PKCS#11 plugin directly,
381  * the application may finish with dlobj and dlclose it.  As the
382  * reference count for libpkcs11(3lib) has become 0, pkcs11_fini()
383  * will be run by the linker.  Even though libpkcs11(3lib) was the
384  * first to initialize the plugin in this case, it is not safe for
385  * libpkcs11(3lib) to finalize the plugin, as the application would
386  * lose state.
387  */
388 static void
389 pkcs11_fini()
390 {
391 	(void) pthread_mutex_lock(&globalmutex);
392 
393 	/* if we're not initilized, do not attempt to finalize */
394 	if (!pkcs11_initialized) {
395 		(void) pthread_mutex_unlock(&globalmutex);
396 		return;
397 	}
398 
399 	fini_called = B_TRUE;
400 
401 	(void) finalize_common(NULL_PTR);
402 
403 	(void) pthread_mutex_unlock(&globalmutex);
404 
405 }
406 
407 CK_RV
408 C_GetInfo(CK_INFO_PTR pInfo)
409 {
410 
411 	/* Check for a fastpath */
412 	if (purefastpath || policyfastpath) {
413 		return (fast_funcs->C_GetInfo(pInfo));
414 	}
415 
416 	if (!pkcs11_initialized)
417 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
418 
419 	if (pInfo == NULL) {
420 		return (CKR_ARGUMENTS_BAD);
421 	}
422 
423 	/*
424 	 * Copy data into the provided buffer, use strncpy() instead
425 	 * of strlcpy() so that the strings are NOT NULL terminated,
426 	 * as required by the PKCS#11 standard
427 	 */
428 	(void) strncpy((char *)pInfo->manufacturerID, MANUFACTURER_ID,
429 	    PKCS11_STRING_LENGTH);
430 	(void) strncpy((char *)pInfo->libraryDescription,
431 	    LIBRARY_DESCRIPTION, PKCS11_STRING_LENGTH);
432 
433 	pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
434 	pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
435 	pInfo->flags = 0;
436 	pInfo->libraryVersion.major = LIBRARY_VERSION_MAJOR;
437 	pInfo->libraryVersion.minor = LIBRARY_VERSION_MINOR;
438 
439 	return (CKR_OK);
440 }
441 
442 /*
443  * This function is unaffected by the fast-path, since it is likely
444  * called before C_Initialize is, so we will not yet know the status
445  * of the fast-path.  Additionally, policy will still need to be
446  * enforced if applicable.
447  */
448 CK_RV
449 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
450 {
451 	if (ppFunctionList == NULL) {
452 		return (CKR_ARGUMENTS_BAD);
453 	}
454 
455 	*ppFunctionList = &functionList;
456 
457 	return (CKR_OK);
458 }
459 
460 
461 /*
462  * This function is no longer supported in this revision of the PKCS#11
463  * standard.  It is maintained for backwards compatibility only.
464  */
465 /*ARGSUSED*/
466 CK_RV
467 C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
468 {
469 	return (CKR_FUNCTION_NOT_PARALLEL);
470 }
471 
472 
473 /*
474  * This function is no longer supported in this revision of the PKCS#11
475  * standard.  It is maintained for backwards compatibility only.
476  */
477 /*ARGSUSED*/
478 CK_RV
479 C_CancelFunction(CK_SESSION_HANDLE hSession)
480 {
481 	return (CKR_FUNCTION_NOT_PARALLEL);
482 }
483