da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
dc20a3024900c47dd2ee44b9707e6df38f7d62a5as * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* protects pkcs11_[initialized|pid], and fastpath */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void pkcs11_init();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void pkcs11_fini();
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Ensure that before a fork, all mutexes are taken.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * We cannot acquire globalmutex, because it can cause deadlock when
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * atfork() and fork() are called in parallel. It can happen when
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * C_Ininitialize() tries to dlopen() a provider. The dlopen() operation
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * is protected by globalmutex and when another thread calls fork()
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * pkcs11_fork_prepare cannot acquire the mutex again and thus it must wait.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When a provider tries to register its atfork handler, atfork() must
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wait on fork(). See the comment in fork() libc function for more details.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 1. slottable->st_mutex
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 2. all slottable->st_slots' mutexes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Take the sl_mutex of all slots */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Ensure that after a fork, in the parent, all mutexes are released in opposite
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * order to pkcs11_fork_prepare().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb /* Release the sl_mutex of all slots */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Ensure that after a fork, in the child, all mutexes are released in opposite
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * order to pkcs11_fork_prepare() and cleanup is done.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Because we need to handle fork correctly before library is initialized two
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * handlers are necessary.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 1) pkcs11_fork_child() - unlock mutexes
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 2) pkcs11_fork_child_fini() - cleanup library after fork, it is registered in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * C_Initialize() after providers initialization.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jbstatic void
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb /* Release the sl_mutex of all slots */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Library cleanup have to be last afterfork child handler. */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * Grab lock to insure only one thread enters
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * this function at a time.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb /* Make sure function hasn't been called twice */
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * A fork has happened and the child is
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * reinitializing. Do a finalize_common() to close
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * out any state from the parent, and then
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb * continue on.
faa1795a28a5c712eed6d0a3f84d98c368a316c6jb /* Check if application has provided mutex-handling functions */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* pReserved should not be set */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Make sure function pointers are either all NULL or
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * all set.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Do not accept application supplied
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * locking primitives.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (initargs->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Calling application does not want the library
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * to create threads. This will effect
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * C_WaitForSlotEvent().
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Initialize slot table */
7b59d02d2a384be9a08087b14defadd214b3c1ddjb /* Get the list of providers */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Load each provider, check for accessible slots,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and populate slottable. If metaslot is enabled,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * it will be initialized as well.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Children inherit parent's atfork handlers */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw (void) pthread_atfork(NULL, NULL, pkcs11_fork_child_fini);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* Cleanup data structures no longer needed */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* Cleanup any data structures that have already been allocated */
return (rv);
static CK_RV
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_ARGUMENTS_BAD);
fast_slot = 0;
pkcs11_pid = 0;
(void) pthread_cond_signal(
(void) pthread_mutex_unlock(
return (rv);
* plugins (like pkcs11_softtoken.so, or any other 3rd party provided
if (!pkcs11_initialized) {
if (!pkcs11_initialized)
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_ARGUMENTS_BAD);
return (CKR_OK);
return (CKR_ARGUMENTS_BAD);
return (CKR_OK);
return (CKR_FUNCTION_NOT_PARALLEL);
return (CKR_FUNCTION_NOT_PARALLEL);