Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

PKCS #11 openCryptoki for Linux

API allows interfacing between cryptographic hardware and user space applications

Steven Bade (sbade@us.ibm.com), Senior Software Engineer, IBM's Linux Technology Center
Steven Bade is a Senior Software Engineer in IBM's Linux Technology Center with 13 years of experience developing networking and network security operating systems software. Steve is the lead developer of the openCryptoki function and has a Bachelor of Science degree in Computer Science from the University of North Carolina at Charlotte. When he isn't programming, Steve can be found scuba diving or out riding his motorcycle. Contact Steve at sbade@us.ibm.com.
Kristin Thomas (kristint@us.ibm.com), Information Developer, IBM's Linux Technology Center
Kristin Thomas is an Information Developer in the Linux Documentation area of IBM's Linux Technology Center. She is a graduate of Texas Tech University with a Master's degree in Technical Communication. Contact Kristin at kristint@us.ibm.com.
Dan Rabinovitz (dsrabino@us.ibm.com), Staff Software Engineer, IBM's Linux Technology Center
Daniel is a Staff Software Engineer in the Network Security area of IBM's Linux Technology Center. He is a graduate of Cornell University with a Bachelor of Science degree in Computer Science. Daniel has experience working on a wide range of projects at a variety of companies, from large corporations to startups. He also has research experience from a position held as an undergraduate research assistant at Cornell University. Contact Daniel at dsrabino@us.ibm.com.

Summary:  Cryptography is rapidly becoming a critical part of our daily lives. However, the application of cryptographic technology adds a heavy computational burden to today's server platforms. More systems are beginning to use specialized hardware to offload the computations, as well as to help ensure the security of secret key material. This article will discuss openCryptoki, an API that is rapidly becoming the de facto, non-Windows-platform industry standard for interfacing between cryptographic hardware and user space applications. In particular, this article will introduce the specifics of the PKCS #11 implementation to IBM cryptographic hardware (openCryptoki) that is available in open source form here on developerWorks.

Date:  01 Nov 2001
Level:  Introductory
Also available in:   Japanese

Activity:  12331 views
Comments:  

What is openCryptoki?

openCryptoki is an implementation of the PKCS #11 API that allows interfacing to devices (such as a smart card, smart disk, or PCMCIA card) that hold cryptographic information and perform cryptographic functions. openCryptoki provides application portability by isolating the application from the details of the cryptographic device. Isolating the application also provides an added level of security because all cryptographic information stays within the device. The openCryptoki API provides a standard programming interface between applications and all kinds of portable cryptographic devices.


Architectural overview

openCryptoki consists of a slot manager and an API for slot token dynamic link libraries (STDLLs). The slot manager runs as a daemon to control the number of token slots provided to applications, and it interacts with applications using a shared memory region. Each device that has a token associated with it places that token into a slot in the slot manager database. The shared memory region allows for proper sharing of state information between applications to help ensure conformance with the PKCS #11 specification.

Slot manager

The slot manager daemon (pkcsslotd) manages slots (and therefore tokens) in the system. A fixed number of processes can be attached to pkcsslotd, so a static table in shared memory is used. The current limit of the table is 1000 processes using the subsystem. The daemon sets up this shared memory upon initialization and acts as a garbage collector thereafter, helping to ensure that only active processes remain registered. When a process attaches to a slot and opens a session, pkcsslotd will make future processes aware that a process has a session open and will lock out certain function calls, if they need exclusive access to the given token. The daemon will constantly search through its region of shared memory and make sure that a process is actually running when it is attached to a token. If an attached process terminates abnormally, pkcsslotd will "clean up" after the process and free the slot for use by other processes.

Main API

The main API for the STDLLs lies in /usr/lib/pkcs11/PKCS11_API.so. This API includes all the functions as outlined in the PKCS #11 API specification. The main API provides each application with the slot management facility. The API also loads token-specific modules (STDLLs) that provide the token-specific operations (cryptographic operations, session management, and object management). STDLLs are customized for each token type and have specific functions, such as an initialization routine, to allow the token to work with the slot manager. When an application initializes the subsystem with the C_Initialize call, the API will load the STDLL shared objects for all the tokens that exist in the configuration (residing in the shared memory) and invoke the token-specific initialization routines.

Slot token dynamic link libraries (STDLLs)

STDLLs are plug-in modules to the main API. They provide token-specific functions beyond the main API functions. Specific devices can be supported by building an STDLL for the device. Each STDLL must provide at least a token-specific initialization function. If the device is an intelligent device, such as a hardware adapter that supports multiple mechanisms, the STDLL can be thin because much of the session information can be stored on the device. If the device only performs a simple cryptographic function, all of the objects must be managed by the software. This flexibility allows the STDLLs to support any cryptographic device.

Shared memory

The slot manager sets up its database in a region of shared memory. Since the maximum number of processes allowed to attach to pkcsslotd is finite, a fixed amount of memory can be set aside for token management. This fixed memory allotment for token management gives applications easier access to token state information and helps ensure conformance with the PKCS #11 specification.


Components of openCryptoki

This section describes the different components of the openCryptoki subsystem.

Slot manager daemon

The slot manager daemon is an executable (/usr/sbin/pkcsslotd) that reads in /etc/pkcs11/pk_config_data, populating shared memory according to what devices have been found on the system. pkcsslotd then continues to run as a daemon. Any other applications attempting to use the subsystem must first attach to the shared memory region and register as part of the API initialization process, so pkcsslotd is aware of the application. If /etc/pkcs11/pk_config_data is changed, pkcsslotd must be stopped and restarted to read in the new configuration file. The daemon can be stopped by issuing the kill <pkcsslotd config> command. The daemon will not terminate if there are any applications using the subsystem.

PKCS11_API.so

This library contains the main API (/usr/lib/pkcs11/PKCS11_API.so) and is loaded by any application that uses any PKCS #11 token that's managed by the subsystem. Before an application uses a token, it must load the API and call C_Initialize, as per the PKCS #11 specification. The loading operation is performed by the application using the dlopen facilities.

Slot Token DLLs (STDLLs)

Three STDLLs ship in the initial offering. These support the IBM 4758 PCI Cryptographic Coprocessor using two different firmware loads, and the IBM Cryptographic Accelerator (ICA), model 2058 or Leeds Lite card.

Note: The compilation process attempts to build all of the tokens that are supported on the target platform, as well as all of the required support programs. If some of the headers and libraries are not present, those components will not be built.

IBM 4758 PCI Cryptographic Coprocessor support
The IBM 4758 PCI Cryptographic Coprocessor (4758 Coprocessor) is a programmable cryptographic coprocessor in a Federal Information Processing Standards 4 (FIPS4) tamper-responding package. As a programmable device, it can be given multiple "personalities." openCryptoki provides STDLLs that interface to two different firmware loads: deep and shallow.

The deep firmware load provides a complete PKCS #11 implementation running on the card. The STDLL in this case converts the host PKCS #11 operations into command blocks that are passed to the card. In this mode, the full security features of the 4758 Coprocessor are available. The shared object loaded by the API module is /usr/lib/pkcs11/stdll/PKCS11_4758.so; however, no applications need to be aware of the name since the configuration process detects and configures the subsystem for the proper tokens. This load is available on the 4758 Coprocessor Web site (see Resources).

The shallow load does not exploit any of the security features of the card. In this case, the STDLL is more complex, providing for PKCS #11 object and session management and allowing the interoperation of multiple processes or threads as the PKCS #11 specification requires. The module loaded by the API is /usr/lib/pkcs11/stdll/PKCS11_LW.so. This firmware is available on a limited basis from IBM, and essentially turns the 4758 Coprocessor into a cryptographic processor.

IBM Cryptographic Accelerator Model 2058 support
The ICA device is modeled after the shallow firmware mode of the 4758 Coprocessor. It provides all of the object and session management facilities, and it exposes the PKCS #11 mechanisms to the application. The API loads the module /usr/lib/pkcs11/stdll/PKCS11_ICA.so on behalf of the application. One unique feature of this module is that it takes advantage of the transparent load balancing provided by the device driver. The subsystem only does one open on the device, but the driver distributes the workload across as many ICA devices as are in the system. With multiple devices in the system, there is a level of fault tolerance. As long as one device in the system is still functional, applications will continue to function but at a degraded level of performance.


Getting started with openCryptoki

This section describes the system requirements for openCryptoki. It also explains where you can get openCryptoki and how to compile and install it.

System requirements

A system running openCryptoki must provide support for at least one of the tokens that are provided with openCryptoki (4758 Cryptographic Coprocessor, ICA model 2058, and the System/390 Linux Cryptographic hardware support).

The following lists show the system requirements for running openCryptoki.

Hardware requirements:

  • x86 PCI bus system, or
  • System/390 with Linux cryptographic hardware support

Software requirements:

  • Linux operating system running at least a 2.2.16 kernel
  • Device drivers and associated support libraries for the installed tokens (some of the header files from those distributions may also be required)

Obtaining openCryptoki

The openCryptoki project is hosted on the IBM developerWorks Web site, and the source is available there. Updates providing bug fixes and functional enhancements are also available on the site.

Compiling and installing openCryptoki

Assuming that the device support (and header files) for the required devices are on the system, you can build openCryptoki by running make from the top-level directory. Using the build target allows for the compilation of the code only. The install target attempts to install the function onto the current system. Setting the INSROOT environment variable will allow you to target a different installation location. The clean target cleans the object files and other build output from the source tree.

If you are building openCryptoki for only one specific device, then the top-level Makefile for the source tree should be modified. Each component has its own Makefile, and the top level Makefile walks through each of its sub-directories building all Makefiles it finds. To build specific components, you do not have to use the top-level Makefile. Running the make -f command in any given sub-directory will build that specific component. Components that have a Linux directory are built from that directory with the make -f ../Makefile.linux command.


Configuring openCryptoki

This section explains the various components and processes associated with configuring openCryptoki.

Configuration utilities

There are three configuration utilities that are part of the openCryptoki kit. These are:

  • /usr/lib/pkcs11/methods/pkcs11_startup
    This utility is an executable shell script that builds the configuration information (/etc/pkcs11/pkcs11_config_data).
  • /usr/lib/pkcs11/methods/4758_status
    This utility is a binary executable that queries the 4758 Coprocessor to determine whether there is a shallow or deep firmware load on the card.
  • /usr/lib/pkcs11/methods/pkcs_slot
    This utility is a shell script that writes the configuration file to disk as /etc/pkcs11/config_data.

To simplify start-up, it is recommended that you create a shell script called /etc/rc.pkcs11. An example of this script is located in the section Preparing the system for configuration.

Configuration files and data stores

Some of the STDLLs require local disk space to store persistent data, such as token information, personal identification numbers (PINs), and token objects. For the shallow 4758 token this information is stored in /etc/pkcs11/4758shallow, and for the ICA device it is stored in /etc/pkcs11/lite. Within each of these directories is a sub-directory, TOK_OBJ, which contains the token object. Each of these STDLLs are limited to 2048 Public and 2048 Private token objects or the disk space allocated to /etc. The configuration scripts automatically create the required directories and assign the required permissions.

Note: The FindObject function's performance is directly related to the number of objects that exist in the system. Applications should be implemented so they don't perform such searches unnecessarily.

The /etc/pkcs11/pk_config_data file stores all of the configuration information for the current tokens within a system. When running, the subsystem's shared memory contains the actual usable configuration information.

Preparing the system for configuration

In order to ensure proper access to openCryptoki tokens, only the root user and users who are members of the "pkcs11" group are allowed to access the subsystem. To properly configure the system, complete the following steps:

  1. Create the "pkcs11" group by running the groupadd pkcs11 command.
    Note: This command is available on Red Hat Linux systems. Consult your Linux distribution's documentation to find out how to add the group if the groupadd command is not included in your implementation.
  2. Add any user ids that will use the subsystem to the pkcs11 group by adding them to the /etc/group file or by using the administrative GUI for your distribution. Alternatively, applications that are owned by the group and are setgid pkcs11 will also be able to run. The configuration detection scripts will create the data storage locations and assign the correct ownerships.
  3. Create a shell script to start the subsystem at system boot.
  4. Add the following script to the local system start-up scripts. For example, on a system running Red Hat Linux, add it as /etc/rc.pkcs11 and add a call to it in /etc/rc.local.
#!/bin/bash
# Sample /etc/rc.pkcs11
# script for starting pkcs#11 at system IPL.
# This should be added to the end of the rc.local script, or
# whatever local startup script for your distribution applies
# Generate the configuration information
/usr/lib/pkcs11/methods/pkcs11_startup
# start the subsystem
/usr/sbin/pkcsslotd
#end of startup script

The configuration scripts of the subsystem interrogate the system, determining which devices are present and putting them into the slot configuration automatically. Assuming that the devices are set up according to their specific instructions, the subsystem will reflect the configuration detected at system boot. If the devices are not found by the pkcs11_startup script, they will not be present. Usually the devices are not found because the modules for the device have not been loaded prior to the invocation of the /etc/rc.pkcs11 script.

PKCS #11 configuration management tools

openCryptoki provides a command line program (/usr/lib/pkcs11/methods/pkcsconf) to configure and administer tokens that are supported within the system. This program provides the same capabilities as running the pkcsconf -? command. These capabilities include token initialization, security officer PIN initializing and changing, and user PIN initializing and changing. Operations that require a specific token must have the slot specified with the -c flag. You can view a list of tokens present within the system by specifying the -s option with no specific slot number. For example, Listing 2shows the options for the pkcsconf command and displays slot information for the system before token initialization:

[root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -?
          /usr/lib/pkcs11/methods/pkcsconf: invalid option -- ?
          usage:  /usr/lib/pkcs11/methods/pkcsconf [-itsmMIupP]
		 [-c slotnumber -U userPIN -S SOPin -n newpin]
                  -i display PKCS11 info
                  -t display token info
                  -s display slot info
                  -m display mechanism list
                  -M display shared memory
                  -I initialize token 
                  -u initialize user PIN
                  -p set the user PIN
                  -P set the SO PIN
          Output of the GetSlotInfo call 
          [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -s
          Slot #0 Info
                  Description: Linux 2.4.2 Linux (ICA)
                  Manufacturer: Linux 2.4.2
                  Flags: 0x1
                  Hardware Version: 0.0
                  Firmware Version: 1.1
          An un-initialized ICA token, the information is obtained via the 
		C_GetTokenInfo call
          [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -i
          PKCS#11 Info
                  Version 2.1 
                  Manufacuter: IBM AIX Software PKCS11          
                  Flags: 0x0  
                  Library Description: Meta PKCS11 LIBRARY              
                  Library VersionToken #0 Info:
                  Label: IBM ICA  PKCS #11               
                  Manufacturer: IBM Corp.                   
                  Model: IBM ICA         
                  Serial Number: 123             
                  Flags: 0x45
                  Sessions: -1/-1
                  R/W Sessions: -1/-1
                  PIN Length: 4-8
                  Public Memory: 0xFFFFFFFF/0xFFFFFFFF
                  Private Memory: 0xFFFFFFFF/0xFFFFFFFF
                  Hardware Version: 1.0
                  Firmware Version: 1.0
                  Time: 11:11:17 AM

This program also allows you to display the subsystem shared memory segment for debugging purposes. Additionally, the program provides some simple query functions on the tokens, such as token info and mechanism list.

Prior to applications using the openCryptoki subsystem, you must perform the following initialization steps (each step is followed by example code):

  1. Initialize the token: Before you use a token, it must be initialized. The key part of this process is assigning a unique label. The security officer PIN is needed (the default for all IBM-provided tokens is 87654321).

    Note: All PINs show up as stars on-screen when entered.
    [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -I -c 0
    Enter the SO PIN: 87654321    
    Enter a unique token label: DraegerICA
    [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -t -c 0
    Token #0 Info:
    Label: DraegerICA                      
    Model: IBM ICA         
    Serial Number: 123             
    Flags: 0x45
    Sessions: -1/-1
    R/W Sessions: -1/-1
    PIN Length: 4-8
    Public Memory: 0xFFFFFFFF/0xFFFFFFFF
    Private Memory: 0xFFFFFFFF/0xFFFFFFFF
    Hardware Version: 1.0
    Firmware Version: 1.0
    Time: 11:14:17 AM
    

  2. Set the security officer PIN: Prudent management practice will have the security officer change the security officer PIN immediately after initializing the token. This procedure prevents unknown individuals from re-initializing the device and removing all of the stored objects (for example, keys and certificates).

    [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -P -c 0
    Enter the SO PIN: 87654321
    Enter the new SO PIN: fredrules
    Re-enter the new SO PIN: fredrules
    

  3. Set the user PIN (by the security officer).

    [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -u -c 0
    Enter the SO PIN: fredrules
    Enter the new user PIN: billybob
    Re-enter the new user PIN: billybob
    

  4. Change the user PIN (by the user).

    [root@draeger /root]# /usr/lib/pkcs11/methods/pkcsconf -p -c 0
    Enter user PIN: billybob
    Enter the new user PIN: 12345678
    Re-enter the new user PIN: 12345678
    


Applications and openCryptoki

This section describes how to make openCryptoki available to applications, and provides an example of how to write such an application.

Making openCryptoki available to applications

Many applications use PKCS #11 tokens. Most of these applications must be configured to load the specific shared object (DLL) for the token. In the case of openCryptoki, only one module (/usr/lib/pkcs11/PKCS11_API.so) must be loaded for access to all the tokens currently running in the subsystem. Multiple token types are supported, with each type taking up a slot in the subsystem according to the implementation specifics of the plug-in module.

If devices are added or removed, the PKCS #11 slot where the token resides may change. For this reason, applications should locate the specific token by the token label provided when the token is initialized and not assume that a specific slot always contains the desired token.

For application-specific configuration information relating to exploitations of PKCS #11, refer to the application's documentation.

Writing an application

To develop an application that uses openCryptoki, you must first load the shared object using the dynamic library calls. Then call C_GetFunctionList. For example, the following routine loads the shared library and gets the function list for subsequent calls:

CK_FUNCTION_LIST  *funcs;
int do_GetFunctionList( void )
{
   CK_RV            rc;
   CK_RV  (*pfoo)();
   void    *d;
   char    *e;
   char    f[]="/usr/lib/pkcs11/PKCS11_API.so";
   printf("do_GetFunctionList...
");
   d = dlopen(f,RTLD_NOW);
   if ( d == NULL ) {
      return FALSE;
   }
   pfoo = (CK_RV (*)())dlsym(d,"C_GetFunctionList");
   if (pfoo == NULL ) {
      return FALSE;
   }
   rc = pfoo(&funcs);
   if (rc != CKR_OK) {
      show_error("   C_GetFunctionList", rc );
      return FALSE;
   }
   printf("Looks okay...
");
   return TRUE;
}

Once loaded, the application must call the C_Initialize function. In the previous example, the function would be invoked with the following lines:

CK_C_INITIALIZE_ARGS cinit_args;
memset(&cinit_args,0x0,sizeof(cinit_args));
funcs->C_Initialize(&cinit_args);

Refer to the PKCS #11 specification available from the RSA Labs Web site (see Resources) for more options.

Note: openCryptoki requires that operating system threads be allowed. If other thread routines are passed in, they are ignored. If the no-os threads argument is set in the initialize arguments structure, the call to C_Initialize will fail.


Sample program

The following sample program prints out all of the current tokens and slots in use in the system. If you want to build the sample program, you will also need the Makefile included after the sample.

Find the sample program here.


Listing 8: Makefile

Conclusion

PKCS #11 is the de facto standard for interfacing to cryptographic hardware devices in a unified manner. openCryptoki represents an open source implementation of PKCS #11 that supports IBM cryptographic hardware on Linux. This support adds a valuable security feature to Linux, strengthening its appeal and commercial viability in the enterprise market.


Resources

About the authors

Steven Bade is a Senior Software Engineer in IBM's Linux Technology Center with 13 years of experience developing networking and network security operating systems software. Steve is the lead developer of the openCryptoki function and has a Bachelor of Science degree in Computer Science from the University of North Carolina at Charlotte. When he isn't programming, Steve can be found scuba diving or out riding his motorcycle. Contact Steve at sbade@us.ibm.com.

Kristin Thomas is an Information Developer in the Linux Documentation area of IBM's Linux Technology Center. She is a graduate of Texas Tech University with a Master's degree in Technical Communication. Contact Kristin at kristint@us.ibm.com.

Daniel is a Staff Software Engineer in the Network Security area of IBM's Linux Technology Center. He is a graduate of Cornell University with a Bachelor of Science degree in Computer Science. Daniel has experience working on a wide range of projects at a variety of companies, from large corporations to startups. He also has research experience from a position held as an undergraduate research assistant at Cornell University. Contact Daniel at dsrabino@us.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Linux
ArticleID=11169
ArticleTitle=PKCS #11 openCryptoki for Linux
publish-date=11012001