Blame doc/opencryptoki-howto.md

Packit 8681c6
# PKCS #11 openCryptoki for Linux HOWTO
Packit 8681c6
Packit 8681c6
v1 - Kristin Thomas - kristint@us.ibm.com
Packit 8681c6
Packit 8681c6
v2 - Eduardo Barretto - ebarretto@linux.vnet.ibm.com
Packit 8681c6
Packit 8681c6
This HOWTO describes the implementation of the RSA Security Inc./Organization
Packit 8681c6
for the Advancement of Structured Information Standards (OASIS) Public Key
Packit 8681c6
Cryptographic Standard #11 (PKCS #11) cryptoki application program interface
Packit 8681c6
(API) on Linux (openCryptoki). The HOWTO explains what services openCryptoki
Packit 8681c6
provides and how to build and install it. Additional resources and a simple
Packit 8681c6
sample program are also provided.
Packit 8681c6
Packit 8681c6
## Table of contents
Packit 8681c6
1. [Copyright Notice and Disclaimer](#1-copyright-notice-and-disclaimer)
Packit 8681c6
2. [Introduction](#2-introduction)
Packit 8681c6
3. [What is openCryptoki?](#3-what-is-opencryptoki)
Packit 8681c6
4. [Architectural Overview](#4-architectural-overview)
Packit 8681c6
    4.1. [Slot Manager](#41-slot-manager)
Packit 8681c6
    4.2. [Main API](#42-main-api)
Packit 8681c6
    4.3. [Slot Token Dynamic Link
Packit 8681c6
    Libraries](#43-slot-token-dynamic-link-libraries)
Packit 8681c6
    4.4. [Shared Memory](#44-shared-memory)
Packit 8681c6
5. [Getting Started with openCryptoki](#5-getting-started-with-opencryptoki)
Packit 8681c6
    5.1. [System Requirements](#51-system-requirements)
Packit 8681c6
    5.2. [Obtaining openCryptoki](#52-obtaining-opencryptoki)
Packit 8681c6
    5.3. [Compiling and Installing
Packit 8681c6
    openCryptoki](#53-compiling-and-installing-opencryptoki)
Packit 8681c6
6. [Configuring openCryptoki](#6-configuring-opencryptoki)
Packit 8681c6
7. [Components of openCryptoki](#7-components-of-opencryptoki)
Packit 8681c6
    7.1. [Slot Manager Daemon](#71-slot-manager-daemon)
Packit 8681c6
    7.2. [libopencryptoki.so](#72-libopencryptokiso)
Packit 8681c6
    7.3. [Slot Token DLLs](#73-slot-token-dlls)
Packit 8681c6
   7.3.1. [Trusted Module Platform](#731-trusted-module-platform-tpm)
Packit 8681c6
   7.3.2. [IBM Cryptographic Architecture (ICA)](#732-ibm-cryptographic-architecture-ica)
Packit 8681c6
   7.3.3. [IBM Common Cryptographic Architecture (CCA)](#733-ibm-common-cryptographic-architecture-cca)
Packit 8681c6
   7.3.4. [Software Token](#734-software-token)
Packit 8681c6
   7.3.5. [IBM Enterprise PKCS #11 (EP11)](#735-ibm-enterprise-pkcs-11-ep11)
Packit 8681c6
   7.3.6. [IBM Integrated Cryptographic Service Facility (ICSF)](#736-ibm-integrated-cryptographic-service-facility-icsf)
Packit 8681c6
8. [Applications and openCryptoki](#8-application-and-opencryptoki)
Packit 8681c6
    8.1. [Making openCryptoki Available to
Packit 8681c6
    Applications](#81-making-opencryptoki-available-to-applications)
Packit 8681c6
    8.2. [Writing an Application](#82-writing-an-application)
Packit 8681c6
9. [Resources](#9-resources)
Packit 8681c6
10. [Appendix A: Sample Program](#10-appendix-a-sample-program)
Packit 8681c6
    10.1. [Sample Program](#101-sample-program)
Packit 8681c6
    10.2. [Makefile](#102-makefile)
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 1. Copyright Notice and Disclaimer
Packit 8681c6
Packit 8681c6
Copyright © 2001 - 2017 IBM Corporation. All rights reserved.
Packit 8681c6
Packit 8681c6
This document may be reproduced or distributed in any form without prior
Packit 8681c6
permission provided the copyright notice is retained on all copies. Modified
Packit 8681c6
versions of this document may be freely distributed, provided that they are
Packit 8681c6
clearly identified as such, and this copyright is included intact.
Packit 8681c6
Packit 8681c6
This document is provided "AS IS," with no express or implied warranties. Use
Packit 8681c6
the information in this document at your own risk.
Packit 8681c6
Packit 8681c6
**Special Notices**
Packit 8681c6
Packit 8681c6
This publication/presentation was produced in the United States. IBM may not
Packit 8681c6
offer the products, programs, services or features discussed herein in other
Packit 8681c6
countries, and the information may be subject to change without notice. Consult
Packit 8681c6
your local IBM business contact for information on the products, programs,
Packit 8681c6
services, and features available in your area. Any reference to an IBM product,
Packit 8681c6
program, service, or feature is not intended to state or imply that only IBM’s
Packit 8681c6
product, program, service, or feature may be used. Any functionally equivalent
Packit 8681c6
product, program, service, or feature that does not infringe on IBM’s
Packit 8681c6
intellectual property rights may be used instead.
Packit 8681c6
Packit 8681c6
Questions on the capabilities of non-IBM products should be addressed to
Packit 8681c6
suppliers of those products. IBM may have patents or pending patent applications
Packit 8681c6
covering subject matter in this presentation. Furnishing this presentation does
Packit 8681c6
not give you any license to these patents. Send license inquiries, in writing,
Packit 8681c6
to IBM Director of Licensing, IBM Corporation, New Castle Drive, Armonk, NY
Packit 8681c6
10504-1785 USA. All statements regarding IBM’s future direction and intent are
Packit 8681c6
subject to change or withdrawal without notice, and represent goals and
Packit 8681c6
objectives only. Contact your local IBM office or IBM authorized reseller for
Packit 8681c6
the full text of a specific Statement of General Direction.
Packit 8681c6
Packit 8681c6
The information contained in this presentation has not been submitted to any
Packit 8681c6
formal IBM test and is distributed "AS IS." While each item may have have been
Packit 8681c6
reviewed by IBM for accuracy in a specific situation, there is no guarantee that
Packit 8681c6
the same or similar results will be obtained elsewhere. The use of this
Packit 8681c6
information or the implementation of any techniques described herein is a
Packit 8681c6
customer responsibility and depends on the customer’s ability to evaluate and
Packit 8681c6
integrate them into the customer’s operational environment. Customers attempting
Packit 8681c6
to adapt these techniques to their own environments do so at their own risk.
Packit 8681c6
Packit 8681c6
The information contained in this document represents the current views of IBM
Packit 8681c6
on the issues discussed as of the date of publication. IBM cannot guarantee the
Packit 8681c6
accuracy of any information presented after the date of publication.
Packit 8681c6
Packit 8681c6
Any performance data in this document was determined in a controlled
Packit 8681c6
environment. Therefore, the results obtained in other operating environments may
Packit 8681c6
vary significantly. Some measurements quoted in this book may have been made on
Packit 8681c6
development-level systems. There is no guarantee these measurements will be the
Packit 8681c6
same on generally-available systems. Some measurements quoted in this book may
Packit 8681c6
have been estimated through extrapolation. Actual results may vary. Users of
Packit 8681c6
this book should verify the applicable data for their specific environment.
Packit 8681c6
Packit 8681c6
A full list of U.S. trademarks owned by IBM may be found at
Packit 8681c6
http://www.ibm.com/legal/copytrade.shtml. Linux is a trademark of Linus
Packit 8681c6
Torvalds. Other company, product, and service names may be trademarks or service
Packit 8681c6
marks of others.
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 2. Introduction
Packit 8681c6
Packit 8681c6
Cryptography is rapidly becoming a critical part of our daily lives. However,
Packit 8681c6
the application of cryptographic technology adds a heavy computational burden to
Packit 8681c6
today's server platforms. More systems are beginning to use specialized hardware
Packit 8681c6
to offload the computations, as well as to help ensure the security of secret
Packit 8681c6
key material. In this HOWTO we will discuss openCryptoki, an API that is rapidly
Packit 8681c6
becoming the defacto, non-Windows-platform industry standard for interfacing
Packit 8681c6
between cryptographic hardware and user space applications. In particular we
Packit 8681c6
will introduce the specifics of the PKCS #11 implementation to IBM cryptographic
Packit 8681c6
hardware (openCryptoki).
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 3. What is openCryptoki?
Packit 8681c6
Packit 8681c6
openCryptoki is an implementation of the PKCS #11 API that allows interfacing to
Packit 8681c6
devices (such as a smart card, smart disk, or PCMCIA card) that hold
Packit 8681c6
cryptographic information and perform cryptographic functions. openCryptoki
Packit 8681c6
provides application portability by isolating the application from the details
Packit 8681c6
of the cryptographic device. Isolating the application also provides an added
Packit 8681c6
level of security because all cryptographic information stays within the device.
Packit 8681c6
The openCryptoki API provides a standard programming interface between
Packit 8681c6
applications and all kinds of portable cryptographic devices.
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 4. Architectural Overview
Packit 8681c6
Packit 8681c6
openCryptoki consists of a slot manager and an API for Slot Token Dynamic Link
Packit 8681c6
Libraries (STDLLs). The slot manager runs as a daemon to control the number of
Packit 8681c6
slots provided to applications, and it interacts with applications using a
Packit 8681c6
shared memory region. Each device that has a token associated with it places
Packit 8681c6
that token into a slot in the slot manager database. The shared memory region
Packit 8681c6
allows for proper sharing of state information between applications to help
Packit 8681c6
ensure conformance with the PKCS #11 specification.
Packit 8681c6
Packit 8681c6
#### 4.1. Slot Manager
Packit 8681c6
Packit 8681c6
The Slot Manager Daemon (_pkcsslotd_) manages slots (and therefore tokens) in
Packit 8681c6
the system. A fixed number of processes can be attached to _pkcsslotd_, so a
Packit 8681c6
static table in shared memory is used. The current limit of the table is 1000
Packit 8681c6
processes using the subsystem. The daemon sets up this shared memory upon
Packit 8681c6
initialization and acts as a garbage collector thereafter, helping to ensure
Packit 8681c6
that only active processes remain registered. When a process attaches to a slot
Packit 8681c6
and opens a session, _pkcsslotd_ will make future processes aware that a process
Packit 8681c6
has a session open and will lock out certain function calls, if the they need
Packit 8681c6
exclusive access to the given token. The daemon will constantly search through
Packit 8681c6
its region of shared memory and make sure that when a process is attached to a
Packit 8681c6
token it is actually running. If an attached process terminates abnormally,
Packit 8681c6
_pkcsslotd_ will "clean up" after the process and free the slot for use by other
Packit 8681c6
processes.
Packit 8681c6
Packit 8681c6
#### 4.2. Main API
Packit 8681c6
Packit 8681c6
The main API for the STDLLs lies in /usr/lib/opencryptoki/libopencryptoki.so.
Packit 8681c6
This API includes all the functions as outlined in the PKCS #11 API
Packit 8681c6
specification. The main API provides each application with the slot management
Packit 8681c6
facility. The API also loads token specific modules (STDLLs) the provide the
Packit 8681c6
token specific operations (cryptographic operations and session and object
Packit 8681c6
management). STDLLs are customized for each token type and have specific
Packit 8681c6
functions, such as an initialization routine, to allow the token to work with
Packit 8681c6
the slot manager. When an application initializes the subsystem with the
Packit 8681c6
__C_Initialize__ call, the API will load the STDLL shared objects for all the
Packit 8681c6
tokens that exist in the configuration (residing in the shared memory) and
Packit 8681c6
invoke the token specific initialization routines.
Packit 8681c6
Packit 8681c6
#### 4.3. Slot Token Dynamic Link Libraries
Packit 8681c6
Packit 8681c6
STDLLs are plug-in modules to the main API. They provide token-specific
Packit 8681c6
functions beyond the main API functions. Specific devices can be supported by
Packit 8681c6
building an STDLLs for the device. Each STDLLs must provide at least a token
Packit 8681c6
specific initialization function. If the device is an intelligent device, such
Packit 8681c6
as a hardware adapter that supports multiple mechanisms, the STDLL can be thin
Packit 8681c6
because much of the session information can be stored on the device. If the
Packit 8681c6
device only performs a simple cryptographic function, all of the objects must be
Packit 8681c6
managed by the software. This flexibility allows the STDLLs to support any
Packit 8681c6
cryptographic device.
Packit 8681c6
Packit 8681c6
#### 4.4. Shared Memory
Packit 8681c6
Packit 8681c6
The slot manager sets up its database in a region of shared memory. Since the
Packit 8681c6
maximum number of processes allowed to attach to _pkcsslotd_ is finite, a
Packit 8681c6
fixed amount of memory can be set aside for token management. This fixed memory
Packit 8681c6
allotment management allows applications easier access to token state
Packit 8681c6
information and helps ensure conformance with the PKCS #11 specification.
Packit 8681c6
Packit 8681c6
### 5. Getting Started with openCryptoki
Packit 8681c6
Packit 8681c6
This section describes the system requirements for openCryptoki. It also
Packit 8681c6
explains where you can get openCryptoki and how to compile and install it.
Packit 8681c6
Packit 8681c6
#### 5.1. System Requirements
Packit 8681c6
Packit 8681c6
openCryptoki installs by default a software token that relies on software to
Packit 8681c6
deliver the crypto functions. So it is possible to install it even if you don't
Packit 8681c6
have physical (hardware) token.
Packit 8681c6
Packit 8681c6
The following lists show the system requirements for running openCryptoki.
Packit 8681c6
Packit 8681c6
**Hardware Requirements**
Packit 8681c6
Packit 8681c6
- openCryptoki is supported on ppc64, s390x and x86.
Packit 8681c6
Packit 8681c6
**Software Requirements**
Packit 8681c6
Packit 8681c6
- Linux operating system running at least a 2.2.16 kernel
Packit 8681c6
- Device drivers and associated support libraries for the installed tokens (some
Packit 8681c6
of the header files from those distributions may also be required)
Packit 8681c6
Packit 8681c6
#### 5.2. Obtaining openCryptoki
Packit 8681c6
Packit 8681c6
The openCryptoki project and source code is hosted on
Packit 8681c6
[GitHub](https://github.com/opencryptoki/opencryptoki). You can find
Packit 8681c6
openCryptoki releases (tarball) on GitHub and, as well, on
Packit 8681c6
[SourceForge](https://sourceforge.net/projects/opencryptoki/).
Packit 8681c6
For any issue, questions or development related subjects, please contact us on
Packit 8681c6
the [mailing list](https://sourceforge.net/p/opencryptoki/mailman/).
Packit 8681c6
Packit 8681c6
#### 5.3. Compiling and Installing openCryptoki
Packit 8681c6
Packit 8681c6
Assuming that the device support (and header files) for the required devices are
Packit 8681c6
on the system, then you can build openCryptoki by entering the source code main
Packit 8681c6
directory and do the following:
Packit 8681c6
Packit 8681c6
1. Run the bootstrap.sh script by typing:
Packit 8681c6
Packit 8681c6
``` $ ./bootstrap.sh ```
Packit 8681c6
Packit 8681c6
2. Configure the source code by typing:
Packit 8681c6
Packit 8681c6
``` $ ./configure ```
Packit 8681c6
Packit 8681c6
   If you're planning to install the package into your home directory or to a
Packit 8681c6
   location other than `/usr/local` then add the flag `--prefix=PATH` to
Packit 8681c6
   `configure`. For example, if your home directory is `/home/luser` you can
Packit 8681c6
   configure the package to install itself there by invoking:
Packit 8681c6
Packit 8681c6
``` $ ./configure --prefix=/home/luser ```
Packit 8681c6
Packit 8681c6
   If your stdll headers and libraries are not under any standard path, you will
Packit 8681c6
   need to pass the paths to your files for the configure script. For instance:
Packit 8681c6
Packit 8681c6
``` $ CPPFLAGS="-L/path/lib" LDFLAGS="-I/path/include" ./configure ```
Packit 8681c6
Packit 8681c6
   See `./configure --help` for info on various options. The default behavior is
Packit 8681c6
   to build a default token implicitly. For the s390 platform, the default token
Packit 8681c6
   is ICA. For other platforms, the default token is the software token. Other
Packit 8681c6
   tokens may be enabled using the corresponding `--enable-<tok>` configuration
Packit 8681c6
   option provided the appropriate libraries are available.
Packit 8681c6
Packit 8681c6
   While running, `configure` prints some messages telling which features is it
Packit 8681c6
   checking for.
Packit 8681c6
Packit 8681c6
3. Compile the package by typing:
Packit 8681c6
Packit 8681c6
``` $ make ```
Packit 8681c6
Packit 8681c6
4. openCryptoki defaults to be usable by anyone who is in the group ``pkcs11``,
Packit 8681c6
Add the pkcs11 group before installing it, by typing as root the command:
Packit 8681c6
Packit 8681c6
``` # groupadd pkcs11 ```
Packit 8681c6
Packit 8681c6
   In addition, add the necessary user to the pkcs11 group (root doesn't need to
Packit 8681c6
   be in the pkcs11 group):
Packit 8681c6
Packit 8681c6
``` # usermod -G pkcs11 <user> ```
Packit 8681c6
Packit 8681c6
5. Type `make install` (as root) to install the programs and any data files and
Packit 8681c6
documentation. During installation, the following files go to the following
Packit 8681c6
directories:
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
    /prefix/sbin/pkcsconf
Packit 8681c6
    /prefix/sbin/pkcsslotd
Packit 8681c6
    /prefix/sbin/pkcsicsf
Packit 8681c6
    /prefix/libdir/libopencryptoki.so
Packit 8681c6
    /prefix/libdir/libopencryptoki.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/libopencryptoki.so
Packit 8681c6
    /prefix/libdir/opencryptoki/libopencryptoki.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/libopencryptoki.so.0.0.0
Packit 8681c6
    /prefix/var/lib/opencryptoki
Packit 8681c6
    /prefix/etc/opencryptoki/opencryptoki.conf
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
   Token objects, which may be optionally built, go to the following locations:
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_cca.so
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_cca.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_cca.so.0.0.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_ep11.so
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_ep11.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_ep11.so.0.0.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_ica.so.0.0.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_icsf.so
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_icsf.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_icsf.so.0.0.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_sw.so.0.0.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so.0
Packit 8681c6
    /prefix/libdir/opencryptoki/stdll/libpkcs11_tpm.so.0.0.0
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
   where `prefix` is either `/usr/local/` or the PATH that you specified in the
Packit 8681c6
   `--prefix` flag. `libdir` is the name of the library directory, for 32-bit
Packit 8681c6
   libraries it is usually `lib` and for 64-bit libraries it is usually `lib64`.
Packit 8681c6
Packit 8681c6
   To maintain backwards compatibility, some additional symlinks are generated
Packit 8681c6
   (note that these are deprecated and applications should migrate to use the
Packit 8681c6
   LSB-compliant name and locations for libraries and executable):
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
    /prefix/lib/opencryptoki/PKCS11_API.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/libopencryptoki.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/opencryptoki/stdll/PKCS11_CCA.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_cca.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/opencryptoki/stdll/PKCS11_EP11.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_ep11.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/opencryptoki/stdll/PKCS11_ICA.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_ica.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/opencryptoki/stdll/PKCS11_ICSF.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_icsf.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/opencryptoki/stdll/PKCS11_SW.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/stdll/libpkcs11_sw.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/pkcs11/PKCS11_API.so
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/libopencryptoki.so
Packit 8681c6
Packit 8681c6
    /prefix/lib/pkcs11
Packit 8681c6
    - Directory created if non-existent
Packit 8681c6
Packit 8681c6
    /prefix/lib/pkcs11/methods
Packit 8681c6
    - Symlink to /prefix/sbin
Packit 8681c6
Packit 8681c6
    /prefix/lib/pkcs11/stdll
Packit 8681c6
    - Symlink to /prefix/lib/opencryptoki/stdll
Packit 8681c6
Packit 8681c6
    /prefix/etc/pkcs11
Packit 8681c6
    - Symlink to /prefix/var/lib/opencryptoki
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
   If any of these directories do not presently exist, they will be created on
Packit 8681c6
   demand. Note that if `prefix` is `/usr`, then `/prefix/var` and `/prefix/etc`
Packit 8681c6
   resolve to `/var` and `/etc`. On the `make install` stage, if content exists
Packit 8681c6
   in the old `/prefix/etc/pkcs11` directory, it will be migrated to the new
Packit 8681c6
   `/prefix/var/lib/opencryptoki` location.
Packit 8681c6
Packit 8681c6
   If you are installing in your home directory make sure that `/home/luser/bin`
Packit 8681c6
   is in your path. If you're using the bash shell add this line at the end of
Packit 8681c6
   your `.bashrc` file:
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
    PATH="/home/luser/bin:${PATH}"
Packit 8681c6
    export PATH
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
   If you are using csh or tcsh, then use this line instead:
Packit 8681c6
Packit 8681c6
``` setenv PATH /home/luser/bin:${PATH} ```
Packit 8681c6
Packit 8681c6
   By prepending your home directory to the rest of the PATH you can override
Packit 8681c6
   systemwide installed software with your own custom installation.
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 6. Configuring openCryptoki
Packit 8681c6
Packit 8681c6
See:
Packit 8681c6
https://www.ibm.com/support/knowledgecenter/linuxonibm/com.ibm.linux.z.lxce/lxce_stackoverview.html
Packit 8681c6
Packit 8681c6
Prior to version 3, openCryptoki used `pk_config_data` as its configuration
Packit 8681c6
file. This file was created upon running `pkcs11_startup`. In version 3,
Packit 8681c6
`pkcs11_startup` and `pk_config_data` have been removed and replaced with a
Packit 8681c6
customizable config file named, `opencryptoki.conf`. It contains an entry for
Packit 8681c6
each token currently supported by openCryptoki. However, only those token, whose
Packit 8681c6
hardware and software requirements are available on the local system, will show
Packit 8681c6
up as present and available upon running the `pkcsconf -t` command.
Packit 8681c6
Packit 8681c6
Before using, each token must be first initialized. You can select the token
Packit 8681c6
with the `-c` command line option; refer to the documentation linked to above
Packit 8681c6
for further instructions.
Packit 8681c6
Packit 8681c6
Initialize a particular token by running `pkcsconf`:
Packit 8681c6
Packit 8681c6
``` $ pkcsconf -I -c ```
Packit 8681c6
Packit 8681c6
In this version of openCryptoki, the default SO PIN is `87654321`. This should
Packit 8681c6
be changed to a different PIN value before use.
Packit 8681c6
Packit 8681c6
You can change the SO PIN by running pkcsconf :
Packit 8681c6
Packit 8681c6
``` $ pkcsconf -P -c ```
Packit 8681c6
Packit 8681c6
You can initialize and change the user PIN by typing:
Packit 8681c6
Packit 8681c6
``` $ pkcsconf -u -c ```
Packit 8681c6
Packit 8681c6
You can later change the user PIN again by typing:
Packit 8681c6
Packit 8681c6
``` $ pkcsconf -p -c ```
Packit 8681c6
Packit 8681c6
### 7. Components of openCryptoki
Packit 8681c6
Packit 8681c6
This section describes the different components of the openCryptoki subsystem.
Packit 8681c6
Packit 8681c6
#### 7.1. Slot Manager Daemon
Packit 8681c6
Packit 8681c6
The slot manager daemon is an executable (`/usr/sbin/pkcsslotd`) that reads in
Packit 8681c6
`/etc/opencryptoki/opencryptoki.conf`, populating shared memory according to
Packit 8681c6
what devices have been found within the system. `pkcsslotd` then continues
Packit 8681c6
running as a daemon. Any other applications attempting to use the subsystem must
Packit 8681c6
first attach to the shared memory region and register as part of the API
Packit 8681c6
initialization process, so `pkcsslotd` is aware of the application. If
Packit 8681c6
`/etc/opencryptoki/opencryptoki.conf/` is changed, `pkcsslotd` must be stopped
Packit 8681c6
and restarted to read in the new configuration file. The daemon can be stopped
Packit 8681c6
by issuing the `pkill pkcsslotd` command or through systemd `systemctl stop
Packit 8681c6
pkcsslotd`. The daemon will not terminate if there are any applications using
Packit 8681c6
the subsystem.
Packit 8681c6
Packit 8681c6
#### 7.2. libopencryptoki.so
Packit 8681c6
Packit 8681c6
This library contains the main API (`/usr/lib/opencryptoki/libopencryptoki.so`)
Packit 8681c6
and is loaded by any application that uses any PKCS #11 token managed by the
Packit 8681c6
subsystem. Before an application uses a token, it must load the API and call
Packit 8681c6
`C_Initialize`, as per the PKCS #11 specification. The loading operation is
Packit 8681c6
performed by the application using the dlopen facilities.
Packit 8681c6
Packit 8681c6
#### 7.3. Slot Token DLLs
Packit 8681c6
Packit 8681c6
Six STDLLs ship in the initial offering. These support Trusted Platfrom Module
Packit 8681c6
(TPM, <2.0), IBM Cryptographic Architecture (ICA), IBM Common Cryptographic
Packit 8681c6
Architecture (CCA), Soft Token, IBM Enterprise PKCS #11 (EP11) and IBM
Packit 8681c6
Integrated Cryptographic Service Facility (ICSF).
Packit 8681c6
Packit 8681c6
    **Note**: The compilation process attempts to build all of the tokens that
Packit 8681c6
    are supported on the target platform, as well as all of the required support
Packit 8681c6
    programs. If some of the headers and libraries are not present, those
Packit 8681c6
    components will not be built.
Packit 8681c6
Packit 8681c6
##### 7.3.1. Trusted Module Platform (TPM)
Packit 8681c6
Packit 8681c6
In order to be able to build the TPM stdll you first need:
Packit 8681c6
Packit 8681c6
1. Enable tpm in BIOS settings.
Packit 8681c6
Packit 8681c6
2. Install trousers, trousers-devel, tpm-tools and tpm-tools-pkcs11 as root.
Packit 8681c6
Package names can differ depending on the Linux distribution.
Packit 8681c6
Packit 8681c6
3. As root run the following commands:
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
    Start the tcsd daemon
Packit 8681c6
    # /etc/init.d/tcsd start  or # systemctl start tcsd
Packit 8681c6
Packit 8681c6
    Enter tpm passwords
Packit 8681c6
    # tpm_takeownership
Packit 8681c6
    Enter owner password:
Packit 8681c6
    Confirm password:
Packit 8681c6
    Enter SRK password:
Packit 8681c6
    Confirm password:
Packit 8681c6
Packit 8681c6
    # tpm_setpresence
Packit 8681c6
    Enter owner password:
Packit 8681c6
    Physical Presence Status:
Packit 8681c6
        Command Enable: true
Packit 8681c6
        Hardware Enable: false
Packit 8681c6
        Lifetime Lock: true
Packit 8681c6
        Physical presence: false
Packit 8681c6
        Lock: true
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
After setting up the TPM the openCryptoki compilation should automatically
Packit 8681c6
build the tpm stdll. If it doesn't, then please run:
Packit 8681c6
Packit 8681c6
``` ./configure --enable-tpmtok ```
Packit 8681c6
Packit 8681c6
For more information check [README.tpm_stdll](README.tpm_stdll)
Packit 8681c6
Packit 8681c6
##### 7.3.2. IBM Cryptographic Architecture (ICA)
Packit 8681c6
Packit 8681c6
The IBM Cryptographic Architecture (ICA) is a hardware token that is available
Packit 8681c6
only for s390 systems. If you are in this platform and have the necessary
Packit 8681c6
hardware, you can build openCryptoki with the ICA stdll. To achieve it you need
Packit 8681c6
first install the `libica` package. This package is available in the Linux
Packit 8681c6
distributions repositories.
Packit 8681c6
Packit 8681c6
##### 7.3.3. IBM Common Cryptographic Architecture (CCA)
Packit 8681c6
Packit 8681c6
The IBM Common Cryptographic Architecture (CCA) is also a hardware token that is
Packit 8681c6
only available for the s390 architecture. If you are in this platform and have
Packit 8681c6
the necessary hardware then you can build openCryptoki with the CCA stdll.
Packit 8681c6
First, you need to install the csulcca library on your system. To get this
Packit 8681c6
package click
Packit 8681c6
[here](https://www-03.ibm.com/security/cryptocards/pciecc2/lonzsoftware.shtml)
Packit 8681c6
and be sure to choose the package corresponding to your crypto card version.
Packit 8681c6
Packit 8681c6
For more information about CCA, read [README.cca_stdll](README.cca_stdll)
Packit 8681c6
and [README.pkcscca_migrate](README.pkcscca_migrate).
Packit 8681c6
Packit 8681c6
##### 7.3.4. Software Token
Packit 8681c6
Packit 8681c6
This token is a software emulation of a token. All the cryptographic operations
Packit 8681c6
needed will be run in a software implementation of such cryptographic
Packit 8681c6
algorithms. This implementation is given by OpenSSL and the Soft token is built
Packit 8681c6
by default with openCryptoki.
Packit 8681c6
Packit 8681c6
##### 7.3.5. IBM Enterprise PKCS #11 (EP11)
Packit 8681c6
Packit 8681c6
This is another hardware token for the s390 architecture. In order to be able to
Packit 8681c6
build openCryptoki with EP11 stdll download the necessary library from
Packit 8681c6
[here](https://www-03.ibm.com/security/cryptocards/pciecc2/lonzsoftware.shtml).
Packit 8681c6
Be sure to choose the driver corresponding to your crypto card version.
Packit 8681c6
Packit 8681c6
For more information about EP11, please refer to
Packit 8681c6
[README.ep11_stdll](README.ep11_stdll).
Packit 8681c6
Packit 8681c6
##### 7.3.6. IBM Integrated Cryptographic Service Facility (ICSF)
Packit 8681c6
Packit 8681c6
The ICSF token is a remote crypto token. The actual crypto operations are
Packit 8681c6
performed remotely on a s390 server and all the PKCS #11 key objects are stored
Packit 8681c6
remotely on the server. This calls to the remote server are done via LDAP. 
Packit 8681c6
Packit 8681c6
So, to build openCryptoki with LDAP, you need to install on the client side:
Packit 8681c6
`openldap, openldap-clients and openldap-devel`.
Packit 8681c6
Packit 8681c6
For more information about ICSF, head over to
Packit 8681c6
[README.icsf_stdll](README.icsf_stdll).
Packit 8681c6
Packit 8681c6
### 8. Application and openCryptoki
Packit 8681c6
Packit 8681c6
This section describes how to make openCryptoki available to applications and
Packit 8681c6
provides an example of how to write such an application.
Packit 8681c6
Packit 8681c6
#### 8.1. Making openCryptoki Available to Applications
Packit 8681c6
Packit 8681c6
Many applications use PKCS #11 tokens. Most of these applications must be
Packit 8681c6
configured to load specific shared object (DLL) for the token. In the case of
Packit 8681c6
openCryptoki, only one module (`/usr/lib/opencryptoki/libopencryptoki.so`) must
Packit 8681c6
be loaded for access to all the tokens currently running in the subsystem.
Packit 8681c6
Multiple token types are supported, with each type taking up a slot in the
Packit 8681c6
subsystem according to the implementation specifics of the plug-in module.
Packit 8681c6
Packit 8681c6
If devices are added or removed, the PKCS #11 slot where the token resides may
Packit 8681c6
change. For this reason, applications should locate the specific token by the
Packit 8681c6
token label provided when the token is initialized and not assume that a
Packit 8681c6
specific slot always contains the desired token.
Packit 8681c6
Packit 8681c6
For application-specific configuration information relating to the exploitations
Packit 8681c6
of PKCS #11, refer to the application's documentation.
Packit 8681c6
Packit 8681c6
#### 8.2. Writing an Application
Packit 8681c6
Packit 8681c6
To develop an application that uses openCryptoki, you must first load the shared
Packit 8681c6
object using the dynamic library calls. Then call C_GetFunctionList. For
Packit 8681c6
example, the following routines loads the shared library and gets the function
Packit 8681c6
list for subsequent calls.
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
CK_FUNCTION_LIST *funcs;
Packit 8681c6
Packit 8681c6
int do_GetFunctionList(void)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;
Packit 8681c6
    CK_RV (*pfoo)();
Packit 8681c6
    void *d;
Packit 8681c6
    char *e;
Packit 8681c6
    char f[]="/usr/lib/pkcs11/PKCS11_API.so"
Packit 8681c6
Packit 8681c6
    printf("do_GetFunctionList...\n");
Packit 8681c6
Packit 8681c6
    d = dlopen(f, RTLD_NOW);
Packit 8681c6
    if (d == NULL)
Packit 8681c6
        return FALSE;
Packit 8681c6
Packit 8681c6
    pfoo = (CK_RV (*)())dlsym(d, "C_GetFunctionList");
Packit 8681c6
    if (pfoo == NULL)
Packit 8681c6
        return FALSE;
Packit 8681c6
Packit 8681c6
    rc = pfoo(&funcs);
Packit 8681c6
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        show_error("C_GetFunctionList rc=%d\n", rc);
Packit 8681c6
        return FALSE;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    printf("Looks okay...\n");
Packit 8681c6
    return TRUE;
Packit 8681c6
}
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
Once loaded, the application must call the `C_Initialize` function. In the
Packit 8681c6
previous example, the function would be invoked with the following lines:
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
CK_C_INITIALIZE_ARGS cinit_args;
Packit 8681c6
memset(&cinit_args, 0x0, sizeof(cinit_args));
Packit 8681c6
funcs->C_Initialize(&cinit_args);
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
Refer to the PKCS #11 specification available from the OASIS web site
Packit 8681c6
(https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11) for more
Packit 8681c6
options.
Packit 8681c6
Packit 8681c6
   **Note**: openCryptoki requires that operating systems threads be allowed. If
Packit 8681c6
   other thread routines are passed in, they are ignored. If the `no-os` threads
Packit 8681c6
   argument is set in the initialize arguments structure, the call to
Packit 8681c6
   C_Initialize will fail.
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 9. Resources
Packit 8681c6
Packit 8681c6
For additional information about PKCS #11 and openCryptoki, see the following
Packit 8681c6
resources:
Packit 8681c6
Packit 8681c6
* openCryptoki on [GitHub](https://github.com/opencryptoki/opencryptoki)
Packit 8681c6
* OASIS [PKCS #11 Specification](https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11)
Packit 8681c6
* [IBM Cryptocards](https://www-03.ibm.com/security/cryptocards/)
Packit 8681c6
* openCryptoki
Packit 8681c6
[mailing-list](https://sourceforge.net/projects/opencryptoki/lists/opencryptoki-tech)
Packit 8681c6
Packit 8681c6
Packit 8681c6
### 10. Appendix A: Sample Program
Packit 8681c6
Packit 8681c6
The following sample program prints out all of the current tokens and slots in
Packit 8681c6
use in the system. If you want to build the sample program, you will also need
Packit 8681c6
the `Makefile` after the sample.
Packit 8681c6
Packit 8681c6
#### 10.1. Sample Program
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
#include <sys/stat.h>
Packit 8681c6
#include <stdlib.h>
Packit 8681c6
#include <errno.h>
Packit 8681c6
#include <stdio.h>
Packit 8681c6
#include <dlfcn.h>
Packit 8681c6
#include <pkcs11types.h>
Packit 8681c6
Packit 8681c6
#define CFG_SLOT        0x0004
Packit 8681c6
#define CFG_PKCS_INFO   0X0008
Packit 8681c6
#define CFG_TOKEN_INFO  0x0010
Packit 8681c6
Packit 8681c6
CK_RV init(void);
Packit 8681c6
CK_RV cleanup(void);
Packit 8681c6
CK_RV get_slot_list(int, CK_CHAR_PTR);
Packit 8681c6
CK_RV display_slot_info(void);
Packit 8681c6
CK_RV display_token_info(void);
Packit 8681c6
Packit 8681c6
void *dll_ptr;
Packit 8681c6
CK_FUNCTION_LIST_PTR    function_ptr = NULL;
Packit 8681c6
CK_SLOT_ID_PTR          slot_list = NULL;
Packit 8681c6
CK_ULONG                slot_count = 0;
Packit 8681c6
int in_slot;
Packit 8681c6
Packit 8681c6
int main(int argc, char *argv[])
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;                   /* Return Code */
Packit 8681c6
    CK_FLAGS flags = 0;         /* Bit Mask for what options were passed in */
Packit 8681c6
    CK_CHAR_PTR slot = NULL;    /* The PKCS slot number */
Packit 8681c6
Packit 8681c6
    /* Load the PKCS11 library */
Packit 8681c6
    init();
Packit 8681c6
Packit 8681c6
    /* Get the slot list and indicate if a slot number was passed in or not */
Packit 8681c6
    get_slot_list(flags, slot);
Packit 8681c6
Packit 8681c6
    /* Display the current token and slot info */
Packit 8681c6
    display_token_info();
Packit 8681c6
    display_slot_info();
Packit 8681c6
Packit 8681c6
    /* We are done, free the memory we may have allocated */
Packit 8681c6
    free(slot);
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV get_slot_list(int cond, CK_CHAR_PTR slot)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;   /* Return code */
Packit 8681c6
Packit 8681c6
    /* Find out how many tokens are present in the slots */
Packit 8681c6
    rc = function_ptr->C_GetSlotList(TRUE, NULL_PTR, &slot_count);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        printf("Error getting number of slots: 0x%X\n", rc);
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Allocate enough space for the slots information */
Packit 8681c6
    slot_list = (CK_SLOT_ID_PTR) malloc(slot_count*sizeof(CK_SLOT_ID));
Packit 8681c6
Packit 8681c6
    rc = function_ptr->C_GetSlotList(TRUE, slot_list, &slot_count);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        printf("Error getting slot list: 0x%X\n", rc);
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return rc;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV display_slot_info(void)
Packit 8681c6
{
Packit 8681c6
    CK_RV           rc;         /* Return Code */
Packit 8681c6
    CK_SLOT_INFO    slot_info;   /* Structure to hold slot information */
Packit 8681c6
    int             lcv;        /* Loop Control Variable */
Packit 8681c6
Packit 8681c6
    for (lcv = 0; lcv < slot_count; lcv++) {
Packit 8681c6
        /* Get the info for the slot we are examining and store in slot_info */
Packit 8681c6
        rc = function_ptr->C_GetSlotInfo(slot_list[lcv], &slot_info);
Packit 8681c6
        if (rc != CKR_OK) {
Packit 8681c6
            printf("Error getting the slot info: 0x%X\n", rc);
Packit 8681c6
            return rc;
Packit 8681c6
        }
Packit 8681c6
Packit 8681c6
        /* Display the slot information */
Packit 8681c6
        printf("Slot #%d Info\n", slot_list[lcv]);
Packit 8681c6
        printf("\tDescription: %.64s\n", slot_info.slotDescription);
Packit 8681c6
        printf("\tManufacturer: %.32s\n", slot_info.manufacturerID);
Packit 8681c6
        printf("\tFlags: 0x%X\n", slot_info.flags);
Packit 8681c6
        printf("\tHardware Version: %d.%d\n", slot_info.hardwareVersion.major,
Packit 8681c6
                                              slot_info.hardwareVersion.minor);
Packit 8681c6
        printf("\tFirmware Version: %d.%d\n", slot_info.firmwareVersion.major,
Packit 8681c6
                                              slot_info.firmwareVersion.minor);
Packit 8681c6
    }
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV display_token_info(void)
Packit 8681c6
{
Packit 8681c6
    CK_RV           rc;         /* Return Code */
Packit 8681c6
    CK_TOKEN_INFO   token_info;  /* Structure to hold token information */
Packit 8681c6
    int             lcv;        /* Loop Control Variable */
Packit 8681c6
Packit 8681c6
    for (lcv = 0; lcv < slot_count; lcv++) {
Packit 8681c6
        /* Get the Token info for each slot in the system */
Packit 8681c6
        rc = function_ptr->C_GetTokenInfo(slot_list[lcv], &token_info);
Packit 8681c6
        if (rc != CKR_OK) {
Packit 8681c6
            printf("Error getting token info: 0x%X\n", rc);
Packit 8681c6
            return rc;
Packit 8681c6
        }
Packit 8681c6
Packit 8681c6
        /* Display the token information */
Packit 8681c6
        printf("Token #%d Info:\n", slot_list[lcv]);
Packit 8681c6
        printf("\tLabel: %.32s\n", token_info.label);
Packit 8681c6
        printf("\tManufacturer: %.32s\n", token_info.manufacturerID);
Packit 8681c6
        printf("\tModel: %.16s\n", token_info.model);
Packit 8681c6
        printf("\tSerial Number: %.16s\n", token_info.serialNumber);
Packit 8681c6
        printf("\tFlags: 0x%X\n", token_info.flags);
Packit 8681c6
        printf("\tSessions: %d/%d\n", token_info.ulSessionCount,
Packit 8681c6
                                      token_info.ulMaxSessionCount);
Packit 8681c6
        printf("\tR/W Sessions: %d/%d\n", token_info.ulRwSessionCount,
Packit 8681c6
                                          token_info.ulMaxRwSessionCount);
Packit 8681c6
        printf("\tPIN Length: %d-%d\n", token_info.ulMinPinLen,
Packit 8681c6
                                        token_info.ulMaxPinLen);
Packit 8681c6
        printf("\tPublic Memory: 0x%X/0x%X\n", token_info.ulFreePublicMemory,
Packit 8681c6
                                               token_info.ulTotalPublicMemory);
Packit 8681c6
        printf("\tPrivate Memory: 0x%X/0x%X\n", token_info.ulFreePrivateMemory,
Packit 8681c6
                                               token_info.ulTotalPrivateMemory);
Packit 8681c6
        printf("\tHardware Version: %d.%d\n", token_info.hardwareVersion.major,
Packit 8681c6
                                              token_info.hardwareVersion.minor);
Packit 8681c6
        printf("\tFirmware Version: %d.%d\n", token_info.firmwareVersion.major,
Packit 8681c6
                                              token_info.firmwareVersion.minor);
Packit 8681c6
        printf("\tTime: %.16s\n", token_info.utcTime);
Packit 8681c6
    }
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV init(void)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;           /* Return Code */
Packit 8681c6
    void (*sym_ptr)();   /* Pointer for the DLL */
Packit 8681c6
Packit 8681c6
    /* Open the PKCS11 API Shared Library, and inform the user if there is an
Packit 8681c6
     * error
Packit 8681c6
     */
Packit 8681c6
    dll_ptr = dlopen("/usr/lib/opencryptoki/libopencryptoki.so", RTLD_NOW);
Packit 8681c6
    if (!dll_ptr) {
Packit 8681c6
        rc = errno;
Packit 8681c6
        printf("Error loading PKCS#11 library: 0x%X\n", rc);
Packit 8681c6
        fflush(stdout);
Packit 8681c6
        return rc;
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    /* Get the list of the PKCS11 functions this token supports */
Packit 8681c6
    sym_ptr = (void (*) ())dlsym(dll_ptr, "C_GetFunctionList");
Packit 8681c6
    if (!sym_ptr) {
Packit 8681c6
        rc = errno;
Packit 8681c6
        printf("Error getting function list: 0x%X\n", rc);
Packit 8681c6
        fflush(stdout);
Packit 8681c6
        cleanup();
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    sym_ptr(&function_ptr);
Packit 8681c6
Packit 8681c6
    /* If we get here, we know the slot manager is running and we can use PKCS11
Packit 8681c6
     * calls, so we will execute the PKCS11 Initialize command.
Packit 8681c6
     */
Packit 8681c6
    rc = function_ptr->C_Initialize(NULL);
Packit 8681c6
    if (rc != CKR_OK) {
Packit 8681c6
        printf("Error initializing the PKCS11 library: 0x%X\n", rc);
Packit 8681c6
        fflush(stdout);
Packit 8681c6
        cleanup();
Packit 8681c6
    }
Packit 8681c6
Packit 8681c6
    return CKR_OK;
Packit 8681c6
}
Packit 8681c6
Packit 8681c6
CK_RV cleanup(void)
Packit 8681c6
{
Packit 8681c6
    CK_RV rc;   /* Return Code */
Packit 8681c6
Packit 8681c6
    /* To clean up we will free the slot list we create, call the Finalize
Packit 8681c6
     * routine for PKCS11 and close the dynamically linked library
Packit 8681c6
     */
Packit 8681c6
    free(slot_list);
Packit 8681c6
    rc = function_ptr->C_Finalize(NULL);
Packit 8681c6
    if (dll_ptr)
Packit 8681c6
        dlclose(dll_ptr);
Packit 8681c6
Packit 8681c6
    exit(rc);
Packit 8681c6
}
Packit 8681c6
```
Packit 8681c6
Packit 8681c6
#### 10.2. Makefile
Packit 8681c6
Packit 8681c6
```
Packit 8681c6
VPATH = ...
Packit 8681c6
Packit 8681c6
INCS = -I../. -I../../../../../include/pkcs11
Packit 8681c6
CFLAGS = $(OPTLVL) $(INCS) -DAPI -DDEV -D_THREAD_SAFE -DLINUX -DDEBUG -DSPINXL
Packit 8681c6
Packit 8681c6
CC = gcc
Packit 8681c6
LD = gcc
Packit 8681c6
Packit 8681c6
LIBS = -ldl -lpthread
Packit 8681c6
Packit 8681c6
OBJS = sample.o
Packit 8681c6
Packit 8681c6
.c.o: ; $(CC) -c $(CFLAGS) -o $@ $<
Packit 8681c6
Packit 8681c6
all: sample
Packit 8681c6
Packit 8681c6
sample: $(OBJS)
Packit 8681c6
${CC} ${OBJS} $(LIBS) -o $@
Packit 8681c6
Packit 8681c6
TARGET = sample
Packit 8681c6
Packit 8681c6
build: $(TARGET)
Packit 8681c6
Packit 8681c6
clean:
Packit 8681c6
rm -f *.so *.o $(TARGET)
Packit 8681c6
```