# Sharing PKCS#11 modules

## Multiple consumers of PKCS#11 in a process

As more and more applications and libraries use PKCS#11 we run into a very basic problem. The PKCS#11 modules cannot be initialized and finalized properly without coordination between the various consumers.

An example: An application might use GnuTLS for TLS connections, and use libgcr for display of certificates. Both of these want to load (and initialize) the same PKCS#11 modules. There are many places where this situation occurs, including large applications like Evolution which due to their dependencies end up using both NSS and GnuTLS.

Consumer A loads a PKCS#11 module and uses the module's C_Initialize function to initialize it, which works as expected. When consumer B initializes the module (also using C_Initialize), the error code `CKR_CRYPTOKI_ALREADY_INITIALIZED` is correctly returned. This is normal PKCS#11 specification defined behavior for when a module is initialized twice in the same process. If consumer B is aware of this situation they may choose to ignore this error code.

However when the consumer A is done with its use of the PKCS#11 module it finalizes the module using the module's C_Finalize function. This is expected of a well behaved PKCS#11 consumer. This then causes errors and/or crashes for consumer B, which cannot know that the module has now been finalized out from underneath it.

It is necessary for the two consumers to coordinate their initialization and finalization in some fashion. In `p11-kit` we provide this coordination in a loosely coupled, backwards compatible, and flexible way.

## Managed modules

`p11-kit` wraps PKCS#11 modules to manage them and customize their functionality so that they are able to be shared between multiple callers in the same process.

Each caller that uses the `p11_kit_modules_load()` or `p11_kit_module_load()` function gets independent wrapped PKCS#11 module(s). This is unless a caller or module configuration specifies that a module should be used in an unmanaged fashion.

When modules are managed, the following aspects are wrapped and coordinated:

- Calls to `C_Initialize` and `C_Finalize` can be called by multiple callers.

  The first time that the managed module `C_Initialize` is called, the PKCS#11 module's actual `C_Initialize` function is called. Subsequent calls by other callers will cause `p11-kit` to increment an internal initialization count, rather than calling `C_Initialize` again.

  Multiple callers can call the managed `C_Initialize` function concurrently from different threads and `p11-kit` will guarantee that this managed in a thread-safe manner.

- When the managed module `C_Finalize` is used to finalize a module, each time it is called it decrements the internal initialization count for that module. When the internal initialization count reaches zero, the module's actual `C_Finalize` function is called.

  Multiple callers can call the managed `C_Finalize` function concurrently from different threads and `p11-kit` will guarantee that this managed in a thread-safe manner.

- Call to `C_CloseAllSessions` only close the sessions that the caller of the managed module has opened. This allows the `C_CloseAllSessions` function to be used without closing sessions for other callers of the same PKCS#11 module.

- Managed modules have ability to log PKCS#11 method calls for debugging purposes. See the `log-calls = yes` module configuration option.

- Managed modules have the ability to be remoted to another machine or isolated in their own process. See the `remote = ...` module configuration option.