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