Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
HPE Atalla NSP PKCS 11 Reference Guide

Introduction

This library supports 2.40 Version of PKCS 11 (see https://www.oasis-open.org/committees/pkcs11/). Included with the PKCS #11 interface definition is one token the HPE NSP token.

P6R's PKCS 11 client follows the standards defined in the following documents.

1) OASIS, PKCS #11 Cryptographic Token Interface Base Specification Version 2.40, OASIS Standard, 14 April 2015, http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.pdf

2) OASIS, PKCS#11 Cryptographic Token Interface Current Mechanisms Specification Version 2.40, OASIS Standard, 14 April 2015, http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/os/pkcs11-curr-v2.40-os.html

3) OASIS, PKCS #11 Cryptographic Token Interface Historical Mechanisms Specification Version 2.40, OASIS Standard, 14 April 2015, http://docs.oasis-open.org/pkcs11/pkcs11-hist/v2.40/os/pkcs11-hist-v2.40-os.html

4) OASIS, OASIS, PKCS #11 Cryptographic Token Interface Usage Guide Version 2.40, Committee Note 02, 16 November 2014, http://docs.oasis-open.org/pkcs11/pkcs11-ug/v2.40/pkcs11-ug-v2.40.html

5) HPE, NSP Atalla Key Block Command Reference Manual, AKB - 1.40, AJ556-9005L, February 2014

Reference 1 above defines and describes the PKCS 11 API in detail and should be used by any programmer using this library. The sections below list all limitations, subsets, and any differences from the official standard caused by limitations of the HPE Atalla NSP product. Reference 4 above also provides in explainations of several key parts of the PKCS #11 standard, such as its security model. The programmer is encouraged to familiar themselves with both of these references.

Includes

This library ships with the standard set of PKCS 11 Version 2.40 ".h" files as defined by the OASIS PKCS #11 Technical committee. These include the files pkcs11.h, pkcs11f.h, and pkcs11t.h. The pkcs11p6r_HPE.h file contains P6R and HPE vendor defined extensions.

Note, the pkcs11.h file is meant to be slightly modified for the particular library and platform and we have made such modifications for use with our library.

Installation, Deployment, and Use

The PKCS 11 library must be installed and deployed in a writable directory. All the files that make up the library reside and run out of a single directory. Once installed a user must configure the slots and tokens before use (see Sections below). Afterwards, a user can either initialize a token via the provided p6pkcs11tool command line tool or via direct calls the the standard PKCS 11 API (e.g., C_InitToken()). The PKCS #11 API can be programmatically accessed by either statically linking to the file p6pkcs11.dll or dynamically loading it and calling the API function C_GetFunctionList() to get function pointers to each API function (note the later is the usual approach).

A Secure Implementation

P6R’s Provider allows any number of slots to be defined and in each slot an NSP token can be configured. For example, it is possible to have a PKCS 11 installation that points to a single NSP HSM where each slot points to a virtual NSP on a different port. It is also possible to configure to use TLS communication to any of the configured NSPs. All slots and tokens are defined via a the p6pkcs11.conf configuration file. All keys and certificates required to communicate with an NSP HSM are themselves securely stored in a PKCS 11 Keystore once the library is initialized.

This library uses a keystore to securely save information about each defined token. This is the PKCS 11 library wide, or master keystore. In addition, each defined NSP token also gets its own dedicated keystore. These keystores are implemented using either a local SQlite database or a local or remote Postgres database. The master keystore is always a local Sqlite database. The default database used for each token is a SQLite database but can be changed with a simple configuration setting (see Section "Basic Configuration Parameters "Keystore" config variable). All keys, certificates, and blobs saved in a keystore are encrypted with its own an AES 256 bit key.

All keys that are generated by the NSP hardware via calls to the PKCS 11 API calls C_GenerateKey or C_GenerateKeyPair are also wrapped in the NSPs MFK [5]. And all of these keys are stored in the keystore dedicated to a token defined in the p6pkcs11.conf file. Thus it is important for the user of this library to take periodic backups of all the keystores as well as the master keystore's AES key. If a token's keystore is deleted or corrupted and there is no corresponding backup then all the NSP keys stored in that token will be lost. Again please note that it is the user's responsibility to safely back up the library's master keystore and all token keystores.

The keystores created by this library are written into the following directory structure.

* installed directory
* PKCS11 -- master keystore
* PKCS11.sig -- cryptographic signature of the PKCS11 file
* pkcs11baseKey.txt -- AES key used to encrypt and sign the PKCS11 file (can be located elsewhere by configuration)
* db -- a directory
* p6pkcs11-slot-0 -- local keystore for the token defined in slot zero (assuming that SQLite is being used)
* p6pkcs11-slot-0.sig -- cryptographic signature of the p6pkcs11-slot-0 file
* p6pkcs11-slot-1 -- local keystore for the token defined in slot one (again assuming that SQLite is being used)
* p6pkcs11-slot-1.sig -- cryptographic signature of the p6pkcs11-slot-0 file
* . . . . -- other slots can also have keystore files
*

Note, that the above is an example and if a Postgres database is used instead of SQLite then the location of these databases will likely be different and under the user's control.

Basic Configuration Parameters

A slot is defined by a section in the p6pkcs11.conf file of the form: "[p6pkcs11-slot-X]". where "X" is replaced with the slot number. Many of the configuration items match to standard slot and token information returned by the C_GetSlotInfo() and C_GetTokenInfo() PKCS 11 API functions.

* [p6pkcs11-gen]
* baseKeyPath="/var/PKCS11/baseKey.txt"
* customerKeyPath="/var/PKCS11/customer1key.txt"
* keystore="/var/PKCS11/keys"
* logDir="/var/log/pkcs11"
* pkcs11LibFlags=3
*
*
* [p6pkcs11-slots-gen]
* slotCount=1
*
*
* [p6pkcs11-tokens]
* HPE1 = "{fbea740e-0857-4da3-bc76-9a67a9e161f0}"
*
* [p6pkcs11-slot-0]
* # Other virtual NPSs at ports: 7100, 7200, 7300, 7400, 7500, 7600, 7700, 7800, 7900
* slotType="HPE1"
* slotFlags=5
* vendorSlotId=0
* tokenNSPIP=10.110.10.28
* tokenNSPPort=7000
* tokenNSPFlags=1
* # tokenNSPCmd="<9A#KEY#>"
* vendorFlags=1
*

The [p6pkcs11-gen] Config Section*

This contains the following PKCS 11 wide configuration parameters:

"baseKeyPath" Config Variable (string Value)

The "baseKeyPath" configuration parameter (string value), is the symmetric key protecting the PKCS 11 keystore is to be written to after it is generated by the library. This parameter can be either a full path to the key file or just the name of the key file. If it is just a file name then it will be treated as relative to the directory the library runs out of. Essentially, this is the one key that is kept in the clear. Either this parameter OR the "customerKeyPath" parameter is defined. If both are defined, then the customerKeyPath parameter will be used.

"customerKeyPath" Config Variable (string Value)

The "customerKeyPath" configuration parameter (string value), is the symmetric key protecting the PKCS 11 keystore. The difference between this parameter and the "baseKeyPath" is that the baseKeyPath key is generated by this command line tool while the customerKeyPath key is provided by the customer. The customer must provide an AES 256 bit PEM encoded file.

"keystore" Config Variable (string value)

The "keystore" configuration parameter (string value), is optional and can be either the full path to a directory where the PKCS 11 library wide keystore is to be created or a database URI of the standard for: "postgresql8://..." (see Keystore documentation). When this parameter is not provided then a default location is used. Otherwise, when using the full path to a local directory then a Sqlite database will be used.

"logdir" Config Variable (string value)

The "logDir" configuration parameter (string value), is optional and when not provided a default location is used. Otherwise, the parameter must be a full path to the diretory where PKCS 11 log statements output should be written to.

"pkcs11LibFlags" Config Variable (positive numeric value)

The "pkcs11LibFlags" configuration parameter (bit mask), is optional and defines special library wide handling or features. Represented as an unsigned integer. The current set of valid bit flags are:

* 0x0001 for Recover PKCS11 keystore from Signature Mismatch error (i.e., 0x80040011),
* 0x0002 force PKCS ll library to use internally created multi-threading locking if no locking already set.
* 0x0004 return CKR_OK for extra calls to C_Initialize instead of returning the error code CKR_CRYPTOKI_ALREADY_INITIALIZED.
* This puts the PKCS 11 library in reference counting mode. This means that each call to C_Initialize must have a matching
* call to C_Finalize and that only the last call to C_Finalize will actually do anything. This does not match the defined
* PKCS 11 standard behavior.
*

(For example, if all 3 flags where set then "pkcs11LibFlags=7" would be the correct value.)

The [p6pkcs11-slots-gen] Config Section

The "[p6pkcs11-slots-gen]" section contains the following PKCS 11 configuration parameters global across all defined slots:

"slotCount" Config Variable (positive decimal integer)

The "slotCount" configuration parameter (positive numeric value), defines the number of slots defined by the p6pkcs11.conf file. Each defined slot gets its own configuration file section such as "[p6pkcs11-slot-X]" where 'X' is replaced with a positive integer starting at zero. With a slotCount of 3 the following configuration file sections should exist: "[p6pkcs11-slot-0]", "[p6pkcs11-slot-1]", "[p6pkcs11-slot-2]".

The [p6pkcs11-tokens] Config Section

The "[p6pkcs11-tokens]" section contains third party token implementations via the p6tokenimpl.h interface definition.

<tokenname> Config Variable (string GUID)

Each item in this section consists of a token "name" with its component GUID. For example: HPE1 = "{fbea740e-0857-4da3-bc76-9a67a9e161f0}", defines a token named "HPE1" with a component GUID of "{3367270E-43E6-4fed-B57A-0711FAE20CCA}" for the NSP HSM token.

The "vendorSlotId" configuration parameter (positive numeric value), is the slot identifier to be used for the 3rd party's token. This is used when the 3rd party token exposes its own PKCS 11 API and will have its own slot numbers to be mapped to.

The "vendorFlags" optional configuration parameter (positive numeric value), is passed into the vendors implementation for the "libWibFlags" parameter of the method p6ITokenImpl::initialize( CK_RV* pRV, P6PKCS11PLUGFLAGS libWideFlags, P6BWCSTR* pTokenType ). The vendor can define their own values or use those defined in the p6tokenimpl.h file.

Low-Level and Debug Logging Configuration

The library provides a very low-level debug logging mechanism and a higher level debug logging mechanism that allows the diagnosis of startup and other library issues. This mechanism does not log protocol related information. See the Basic Configuration Parameters section for details on configuring protocol logging. This mechanism is intended to help debug library startup and other non-protocol related issues.

Low-Level Logging

The low level logging is a failsafe log to provide diagnostics for log creation. If the debug log is not being created, then this is the place to look for information on why that may be. When the library loads, it will always create this file in the temp directory and it will be named "p6cryptoki-startup.log". On most Linux systems it will be created the "/tmp" directory. If you system does not have a "/tmp", then it will try "/usr/tmp" and then "/var/tmp". This file is overwritten each time the library is loaded.

Debug Logging

Debug logging is enabled by placing a file in the same directory as the pksc11 shared library. When the library is first loaded and starts up, it will look for this file and if found will begin sending log output to it. The filename itself controls what is logged. For example, if the pkcs11 shared library is located in "/opt/product/bin" then a file named "p6cryptoki-info.log" will enable logging of "info" and "errors" level log messages into that file.

To disable logging, the pkcs11 shared library will need to be unloaded and the log file deleted or renamed to something that does not start with "p6cryptoki".

Controlling What Is Logged In The Debug Log

To change what information is logged, the log filename is changed by adding dash separated log-level qualifiers to the filename to indicate which log-levels are to be included in the log output. The allowable log-level qualifiers are "debug", "info", "warn" and "all". Errors are always logged.

The following table illustrates the naming convention that is used:

FilenameDescription
p6cryptoki.logIf no qualifiers are added, then only errors will be logged.
p6cryptoki-debug.logSince errors are always logged, this would log "debug" and "error" log messages.
p6cryptoki-info.logSince errors are always logged, this would log "info" and "error" log messages.
p6cryptoki-warn.logSince errors are always logged, this would log "warn" and "error" log messages.
p6cryptoki-all.logThis is shorthand for enabling all log-levels.
p6cryptoki-info-warn.logMultiple qualifiers can be used. Since errors are always logged, this would log "info", "warn" and "error" log messages.
P6CRYPTOKI-waRn-Info.lOgMultiple qualifiers can be used and are case insenitive. This is identical in function to the previous example.

Note that qualifiers can be specified in any order and are case-insensitive.

P6R's Command Line Tool

P6R’s PKCS 11 library also ships with a command line tool. This executable is a PKCS 11 application in that it dynamically loads our library and calls C_GetFunctionList in order to obtain the API function pointers. A user can use this command line tool to initialize a token, set the SO or User’s PIN, list all configured slots, list information on a token, generate keys, import and export some certificates and keys, and list the contents of a token.

The command line tool is an executable that can be found in the "bin" directory in a SKC release. Executing it without any parameters (or with "-h" for help) will display usage documentation showing its current set of functionality.

Hewlett Packard Enterprise (HPE) Atalla HSM Network Security Processor (NSP) Integration

An HPE's Atalla HSM (http://www8.hp.com/us/en/software-solutions/hardware-security-module-hsm-atalla-nsp/) can be configured to look like another token. We map one P6R's PKCS11 library slot to one NSP HSM. In the case where an NSP is configured with multiple Virtual NSPs then we map one P6R's PKCS11 library slot to one Virtual NSP. In the example below, both P6R slot numbers 2 and 3 are mapped to one physical HPE machine but to two virtual NSPs. In the example, each Virtual NSP is selected by the port (i.e., tokenNSPPort parameter).

This token supports the following PKCS 11 mechanisms: CKM_AES_KEY_GEN, CKM_DES_KEY_GEN, CKM_DES2_KEY_GEN, CKM_DES3_KEY_GEN, CKM_SHA_1_HMAC, CKM_SHA256_HMAC, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS, CKM_RSA_X_509, CKM_DES_CBC, CKM_DES_CBC_PAD, CKM_DES_CFB8, CKM_DES_CFB64, CKM_DES_OFB64, CKM_DES3_CBC (CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP), CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512, CKM_MD2, CKM_MD5, and CKM_RIPEMD160. All digest calculations are done in the PKCS 11 client with the use of OpenSSL, but all other calculations are done on the NSP.

This token supports the following PKCS 11 API functions: C_Initialize, C_Finalize, C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, C_GetMechanismInfo, C_InitToken, C_InitPIN, C_SetPIN, C_OpenSession, C_CloseSession, C_CloseAllSessions, C_GetSessionInfo, C_Login, C_Logout, C_CreateObject, C_DestroyObject, C_GetAttributeValue, C_SetAttributeValue, C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal, C_GenerateRandom, C_GenerateKey (not including domain parameters), C_GenerateKeyPair, C_SignInit, C_Sign, C_SignUpdate, C_SignFinal, C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal, C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal, C_EncryptInit, C_Encrypt, C_EncryptUpdate, C_EncryptFinal, C_DecryptInit, C_Decrypt, C_DecryptUpdate, C_DecryptFinal, C_WrapKey, and C_UnwrapKey.

This token supports the following PKCS 11 objects: CKO_CERTIFICATE, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_SECRET_KEY, and CKO_DATA.

For this and all 3rd party tokens the PKCS 11 API functions: C_GetInfo, C_GetFunctionList, C_GetSlotList, and C_CloseAllSessions are handled by the PKCS 11 provider module that dynamically loads all tokens).

The HPE Atalla token does not support any of the following attributes to be passed in as part of the pTemplate parameter of the C_FindObjectsInit API call: CKA_VALUE, CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_EC_PARAMS, and CKA_EC_POINT. If any of these attributes are used C_FindObjectsInit will return the CKR_ARGUMENTS_BAD error.

The Atalla NSP HSM's AKB key format attaches how a key can be used to the key material. The NSP key usage is simple compared to what is possible via the PKCS11 API. As such the NSP token limits what a calling application can specify when creating symmetric key objects only to the following sets: { CKA_ENCRYPT, CKA_DECRYPT }, or { CKA_SIGN, CKA_VERIFY }, or { CKA_WRAP, CKA_UNWRAP } are the only combinations of attributes used to define symmetric key usage that can be set to CK_TRUE at the same time. Thus, for example, trying to set a set of { CKA_ENCRYPT, CKA_SIGN } for a symmetric key will result in an error being returned CKR_TEMPLATE_INCONSISTENT because it is not possible to create a symmetric key on the NSP AKB format with that type of key usage.

The following default attribute values are used if the calling application does not define a value:

* CKA_TOKEN - CK_FLASE
* CKA_DERIVE - CK_FALSE (for CKO_SECRET, CKO_PUBLIC, CKO_PRIVATE keys)
* CKA_SENSITIVE - is always CK_TRUE (except for public keys) since all keys are wrapped in the NSP's MKF
* CKA_ALWAYS_SENSITIVE - is always CK_TRUE (except for public keys)
* CKA_CERTIFICATE_CATEGORY - CK_CERTIFICATE_CATEGORY_UNSPECIFIED (for CKO_CERIFICATE objects)
*

Note that in the PKCS #11 standard the function C_InitToken can be called multiple times. On the very first successful call the token is initialized. Then on any subsequent calls the token is supposed to be re-initialized, which includes deleting all contents on a token. In order to prevent accidental deletion of NSP keys stored in a token our implementation of C_InitToken does not clear the token or replace the label. However, additional calls to C_InitToken can be used to load new TLS credentials into the token that might have expired. This does not stop the deletion of individual keys

The HPE NSP token allows PIN values to contain any valid UTF8 character just as defined by the PKCS#11 standard (Section 5.5, C_InitToken).

* [p6pkcs11-tokens]
* HPE1 = "{fbea740e-0857-4da3-bc76-9a67a9e161f0}"
*
* [p6pkcs11-slot-2]
* # Other virtual NPSs at ports: 7100, 7200, 7300, 7400, 7500, 7600, 7700, 7800, 7900
* slotType="HPE1"
* slotFlags=5
* vendorSlotId=2
* tokenNSPIP=10.110.10.28
* tokenNSPPort=7000
* tokenNSPFlags=1
* # tokenNSPCmd="<9A#KEY#>"
* vendorFlags=1
*
* [p6pkcs11-slot-3]
* slotType="HPE1"
* slotFlags=5
* vendorSlotId=3
* tokenNSPIP=10.110.10.28
* tokenNSPPort=7100
* tokenNSPFlags=3
* tokenTLSRootPEM="CACERT_7100.pem"
* tokenConnectTimeout = 60000
* tokenSendTimeout = 60000
* tokenReceiveTimeout = 120000
* vendorFlags=1
* # tokenSoftKeystore = "postgresql8://unittester/unittester/unitsrv1.corp.p6r.com//5432/pkcs11"));
*

The NSP has no notion of PKCS11 slots so we set the "vendorSlotId" parameter to the same slot number as the P6R slot number (e.g., "vendorSlotId=2" is set for "[p6pkcs11-slot-2]" above).

The "slotFlags" configuration parameter (positive numeric value), maps to the "flags" field of the CK_SLOT_INFO PKCS 11 API structure. Valid values of this flag field are defined in the specification: PKCS #11 Cryptographic Token Interface Base Specification Version 2.40, Section 3.2 Slot and token types, Table 5, Slot Information Flags. For example, these values for PKCS#11 Version 2.40:

* CKF_TOKEN_PRESENT 0x00000001
* CKF_HW_SLOT 0x00000004
*

So for example, our KMIP token should have the value '5' for this parameter since the token is present and its a Hardware slot. However, our software token should only have a value of '1' for this parameter.

The "vendorSlotId" configuration parameter (positive numeric value), is the slot identifier to be used for the 3rd party's token. This is used when the 3rd party token exposes its own PKCS#11 API and will have its own slot numbers to be mapped to.

The "tokenNSPIP" configuration parameter (string value) is used to configure the IP address of the NSP hardware.

The "tokenTLSRootPEM" configuration parameter (string value) points to a file that contails the TLS root certificate of the NSP. This allows standard TLS network connection to be made to the NSP (see slot 3 above). This certificate can be replaced by a call to C_InitToken() or by use of the PKCS 11 command line took "-it" (i.e., initialize token) function. This certificate replacement is done on an already initialized token and can be used to replace an expired certificate. The HPE token does NOT delete anything else during a call to C_InitToken(). Note that the replace certificate must have the same subject as the previously configured certificate.

The "tokenNSPFlags" configuration parameter (bit mask) defines token specific configuration options. This parameter is an unsigned integer bit mask of the following flags: { 0x0001 - log NSP messages, 0x0002 - use TLS for network connections, 0x0004 - C_SeedRandom always returns CKR_OK, 0x0008 - use 'p' NSP key usage for RSA key generation [and allows the use of the cipher CKM_RSA_X_509]}. This parameter has a default value of 0x0002 - use TLS.

The "tokenMaxBufSize" configuration parameter (positive numeric value) defaults to "65556" bytes and defines the size of the NSP tokens buffers.

The "tokenConnectTimeout", "tokenSendTimeout", and "tokenReceiveTimeout" configuration parameters (positive numeric values) pass to the NSP token network timeouts in milliseconds for TCP connection, send, and receive operations respectively. The tokenConnectTimeout and tokenSendTimeout parameters have a default value of 60000 milliseconds while the tokenReceiveTimeout parameter has a default value of 300000 milliseconds.

The "tokenNSPCmd", is an optional configuration parameter (string value) used to send an out-of-band command to the NSP HSM when C_GetTokenInfo() is called, or when the "-lt" list token option is used in the PKCS#11 Command Line Tool. If logging is turned on the user can then see the response from the NSP. This parameter can take any ASCII NSP command sequence upto 3000 characters long.

The "vendorFlags" is an optional configuration parameter (bit mask) and for this token can have the following values: { 0x0001 - recover bad signature (when the signature on the NSP token's keystore fails allow us to open it anyway) }

The "tokenSoftKeystore" configuration parameter (string value), is optional and can either the full path to a directory where the slot's keystore is to be created or a database URI of the standard for: "postgresql8://...". When this parameter is not provided then a default location is used. Otherwise, When using the full path to a local directory then a Sqlite database will be used. This keystore holds all the PKCS 11 defined objects for this token (e.g., CKO_SECRET_KEY, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_CERIFICATE).

The "tokenMinPinLen" configuration parameter (positive numeric value), defines the smallest number of bytes of length that a PIN is allowed to be for a token. The defailt value is 8.

The "tokenMaxPinLen" configuration parameter (positive numeric value), defined the largest number of bytes of length that a PIN is allowed to be for a token. The default value is 25.

NSP Command and Response Logging

Sometimes it is necessary to see both the NSP command from the PKCS#11 library and the NSP response form the Atalla HSM to diagnose a problem. To do this the following configuration is required: {1) tokenNSPFlags has to have the 0x0001 bit in that bit mask on, and (2) the file p6pkcs11.en_us requires the following modification.

* [hpe.com.pkcs11]
* libraryTrace = "info",2,"HPE NSP token, %1$ (error: %2$, %6$) (extra1: %3$ %4$) (extra2: %5$)"
* nspIncompleteMsg = "info",2,"HPE NSP token [%1$:%2$], incomplete response [%3$] length: %4$"
* nspCommand = "info",2,"HPE NSP token [%1$:%2$], command [%3$] sent: %4$"
* nspResponse = "info",2,"HPE NSP token [%1$:%2$], response [%3$] received: %4$"
* tokenTrace = "info",2,"HPE NSP token, %1$ (error: %2$, %6$) (extra1: %3$ %4$) (extra2: %5$)"
*

Change in the above section the '2' to '0' which is the log level. Once the value is '0' then these log statements will appear in the logs showing all the NSP commands and their matching PKCS#11 calls.

AES ENCRYPTION ON HPE TOKEN

On older HPE Atalla HSMs, in order to perform AES encryption on the HPE Atalla HSM the AES key has to be created using the SCA device. Then that AES key, in AKB format encrypted under the NSP's MFK can be loaded directly into the P6R token via the following PKCS#11 code. (Note, newer model HSMs allow AES key generation via the PKCS#11 API.)

* // -> load the AES key into the token
* CK_ATTRIBUTE keyTemplate[15];
* CK_UTF8CHAR label[] = "AESkey1";
* CK_BBOOL bTFlag = CK_TRUE;
* CK_ULONG keyLength = 32; // -> key length in bytes
* CK_RV rv = CKR_OK;
*
* // -> 256 bit NSP key generated under our MFK
* static P6CHAR* pKeyMaterial = (P6CHAR*)"1DJNE000,10C229E920E1B4FDD967E4EBB1B03F919EFE7FC70ED398527F1BCC27F75811AC,4851CE59462C88A4";
*
* --- assume PKCS#11 code that calls C_OpenSession( hSession ) and C_Login()... ---
*
* keyTemplate[0].type = CKA_CLASS;
* keyTemplate[0].pValue = &objClass;
* keyTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
* keyTemplate[1].type = CKA_KEY_TYPE;
* keyTemplate[1].pValue = &keyType;
* keyTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
* keyTemplate[2].type = CKA_TOKEN;
* keyTemplate[2].pValue = &bTFlag;
* keyTemplate[2].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[3].type = CKA_LABEL;
* keyTemplate[3].pValue = label;
* keyTemplate[3].ulValueLen = 7;
* keyTemplate[4].type = CKA_VALUE_LEN;
* keyTemplate[4].pValue = &keyLength;
* keyTemplate[4].ulValueLen = sizeof(CK_ULONG);
* keyTemplate[5].type = CKA_ENCRYPT;
* keyTemplate[5].pValue = &bTFlag;
* keyTemplate[5].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[6].type = CKA_DECRYPT;
* keyTemplate[6].pValue = &bTFlag;
* keyTemplate[6].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[7].type = CKA_VALUE;
* keyTemplate[7].pValue = pKeyMaterial;
* keyTemplate[7].ulValueLen = 90;
* rv = C_CreateObject( hSession, (CK_ATTRIBUTE_PTR)keyTemplate,8, &hKey );
*

First, notice the use of a vendor defined CK_KEY_TYPE 'CKK_HPE_AES_NSPWRAPPED'. This value is defined in the file pkcsllp6r.h. It is this value that informs the HPE token how to handle the contents of the CKA_VALUE attribute. Second, the actual NSP key referred to by the pKeyMaterial variable in the above example can be read in from a file. Third, an AES key can also be imported into the HPE token by use of P6R's PKCS11 Command Line Tool from a file. Once the key is loaded into the HPE token it can be used just like any key that was created via a C_GenerateKey() and C_GenerateKeyPair() call.

The above scheme can also be used to load in DES and RSA NSP keys with the use of the following vendor defined key types (see file pkcs11p6r.h): CKK_HPE_DES_NSPWRAPPED. CKK_HPE_DES2_NSPWRAPPED, CKK_HPE_DES3_NSPWRAPPED, CKK_HPE_RSAPUB_NSPWRAPPED, and CKK_HPE_RSAPRV_NSPWRAPPED.

KEY EXPORT IN NON-AKB FORMAT ON HPE TOKEN

If a user wishes to export a key currently stored in the HPE token into a non-AKB format the following steps need to take place. First, the user needs to generate a KEK using the SCA device. This KEK is then loaded into the HPE token either using the approach described above or via the PKCS11 Command Line Tool. Note, that such a key MUST have the CK_WRAP PKCS#11 attribute set. Here is the PKCS#11 code to do export a key:

* CK_ATTRIBUTE keyTemplate[15];
* CK_BYTE exportBuf[600];
* CK_ULONG exportLength = 600;
* CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
* CK_KEY_TYPE keyType = CKK_HPE_DES3_NSPWRAPPED;
* CK_UTF8CHAR label[] = "ExportKEK1";
* CK_BBOOL bTFlag = CK_TRUE;
* CK_ULONG keyLength = 24;
* CK_RV rv = CKR_OK;
* CK_MECHANISM wrapMech = { CKM_DES3_CBC, NULL_PTR, 0 };
*
* // Here are new AKB-KEKs based on this triple length KEK: 0123456789ABCDEF FEDCBA9876543210 5454676776768989, check digits B51E
* //
* // -> KEK for exporting keys, for C_Wrap()
* static P6CHAR* pExportKEK = (P6CHAR*)"1KDNE000,7BC98D21224A2C8579928F06D498C48F2250CA1DBF3C8316,8224EDAC00A8E8C3";
*
* --- assume PKCS#11 code that calls C_OpenSession( hSession ) and C_Login()... ---
*
* // -> first load the KEK into the HPE token
* keyTemplate[0].type = CKA_CLASS;
* keyTemplate[0].pValue = &objClass;
* keyTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
* keyTemplate[1].type = CKA_KEY_TYPE;
* keyTemplate[1].pValue = &keyType;
* keyTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
* keyTemplate[2].type = CKA_TOKEN;
* keyTemplate[2].pValue = &bTFlag;
* keyTemplate[2].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[3].type = CKA_LABEL;
* keyTemplate[3].pValue = label;
* keyTemplate[3].ulValueLen = 10;
* keyTemplate[4].type = CKA_VALUE_LEN;
* keyTemplate[4].pValue = &keyLength;
* keyTemplate[4].ulValueLen = sizeof(CK_ULONG);
* keyTemplate[5].type = CKA_WRAP; // -> HAS TO BE SET
* keyTemplate[5].pValue = &bTFlag;
* keyTemplate[5].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[6].type = CKA_VALUE;
* keyTemplate[6].pValue = pExportKEK;
* keyTemplate[6].ulValueLen = 74;
* rv = C_CreateObject( hSession, (CK_ATTRIBUTE_PTR)keyTemplate, 7, &hExportKEK );
*
* --- assume PKCS#11 code puts a valid handle into hDataKey to export, could be using C_FindObjects() ... ---
*
* // -> export the data key by wrapping it in the Export KEK without the AKB format
* rv = C_WrapKey( hSession, &wrapMech, hExportKEK, hDataKey, (CK_BYTE_PTR)exportBuf, &exportLength );
*
*

At the end of the above example the buffer 'exportBuf' contents the data key wrapped using the key referenced by 'pExportKEK'. Note that the original data key, referenced to by the handle 'hDataKey', still exists in the HPE token (i.e., the C_Wrap() key function does not remove the key).

KEY IMPORT FROM NON-AKB FORMAT ON HPE TOKEN

If a user wishes to import a key that has previously been exported using the C_Wrap() call of the HPE token, or from an Atalla NSP directly via Command 1A, the following steps are required. First, the user needs to generate the proper import KEK using the SCA device for the NSP importing the key. This means, of course, that the same "in-the-clear" key material used for the export KEK (see above example) has to be re-used. What is different for importing is that the key usage of the final import key has to be taken into account in order to generate the proper AKB format. So if the final imported key is to be used for encrypt / decrypt operations then it must use a KEK for data keys, whereas if the imported key is to be used for HMAC operations then a different KEK is to be generated (refer to NSP documentation).

In the example below, we show several different KEK keys for importing wrapped keys. Second, once generated these import KEK keys must be loaded into the HPE token (see example above).

* CK_ATTRIBUTE importTemplate[15];
* CK_BYTE importBuf[600];
* CK_ULONG importLength = 600;
* CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
* CK_KEY_TYPE keyType = CKK_DES3;
* CK_UTF8CHAR label[] = "ImportedDESKey";
* CK_BBOOL bTFlag = CK_TRUE;
* CK_ULONG keyLength = 24;
* CK_RV rv = CKR_OK;
* CK_MECHANISM wrapMech = { CKM_DES3_CBC, NULL_PTR, 0 };
*
* // Here are AKB-KEKs based on this triple length KEK: 0123456789ABCDEF FEDCBA9876543210 5454676776768989, check digits B51E
* //
* // -> KEK for exporting keys, for C_Wrap()
* static P6CHAR* pExportKEK = (P6CHAR*)"1KDNE000,7BC98D21224A2C8579928F06D498C48F2250CA1DBF3C8316,8224EDAC00A8E8C3";
*
* // -> KEK for importing data keys, for C_Unwrap()
* static P6CHAR* pDataKEK = (P6CHAR*)"1DDNE0I0,83A485EE47EB6E2B2BF59D9E760443CC513313F97AEE93B6,E0C8DEFF7A2E999E";
*
* // -> KEK for importing HMAC-SHA1 keys, for C_Unwrap()
* static P6CHAR* pHMAC1KEK = (P6CHAR*)"1MHNE0I0,E09377F1DF056250E480D3C2264217C9C15AA5AD7C889A08,36C56D78866C0F08";
*
* // -> KEK for importing MAC keys (commands 98, 99), for C_Unwrap()
* // static P6CHAR* pMACKEK = (P6CHAR*)"1M2NE0I0,620A298F878FEE056FF0E6842CF83C3008485F1718E7DDB6,5D91A0D98D2A855F";
*
* --- assume PKCS#11 code that calls C_OpenSession( hSession ) and C_Login()... ---
*
* --- add PKCS#11 code to load the pDataKEK into the token (see previous example), sets the value in hImportDataKEK ... ---
*
* --- assume code that gets the wrapped key to import to be placed into the importBuf array ... ---
*
* // -> import back in the DES3 key we exported in the last example
* importTemplate[0].type = CKA_CLASS;
* importTemplate[0].pValue = &objClass;
* importTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
* importTemplate[1].type = CKA_KEY_TYPE;
* importTemplate[1].pValue = &keyType;
* importTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
* importTemplate[2].type = CKA_TOKEN;
* importTemplate[2].pValue = &bTFlag;
* importTemplate[2].ulValueLen = sizeof(CK_BBOOL);
* importTemplate[3].type = CKA_LABEL;
* importTemplate[3].pValue = label;
* importTemplate[3].ulValueLen = 14;
* importTemplate[4].type = CKA_VALUE_LEN;
* importTemplate[4].pValue = &keyLength;
* importTemplate[4].ulValueLen = sizeof(CK_ULONG);
* importTemplate[5].type = CKA_ENCRYPT;
* importTemplate[5].pValue = &bTFlag;
* importTemplate[5].ulValueLen = sizeof(CK_BBOOL);
* importTemplate[6].type = CKA_DECRYPT;
* importTemplate[6].pValue = &bTFlag;
* importTemplate[6].ulValueLen = sizeof(CK_BBOOL);
* rv = C_UnwrapKey( hSession, &wrapMech, hImportDataKEK, importBuf, importLength, (CK_ATTRIBUTE_PTR)importTemplate, 7, &hDataKey );
*
*

At the end of the above example the wrapped key that was in importBuf has been decrypted using the value represented by the 'pDataKEK' and re-encrypted using the NSP's MFK. The newly imported key is in AKB format and is loaded into the HPE token with the hDataKey handle pointing to it. In the above example, we imported the key with the key useage for encrypt / decrypt operations and so we also needed to set the PKCS#11 CKA_ENCRYPT and CKA_DECRYPT attributes (see above).

Introduction

This library supports 2.40 Version of PKCS 11 (see https://www.oasis-open.org/committees/pkcs11/). It currently supports two types of "fixed" tokens. The first token is a KMIP server (see https://www.oasis-open.org/committees/kmip/). The second token is P6R's software token which uses P6R's Powerful Keystore (see https://www.p6r.com/articles/2011/06/05/key-management-with-a-powerful-keystore/) to store all PKCS 11 objects (e.g., CKO_SECRET_KEY, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_CERIFICATE, CKO_DOMAIN_PARAMTERS, CKO_DATA). Any number of slots can be defined and in each slot either type of token can be configured. For example, it is possible to have a PKCS 11 installation that points to several different KMIP servers and several different P6R software token instances each separate from the others. One of the benefits of the PKCS 11 API is that it provides a standard based Keystore API.

The current library meets the requirements for conformance of a PKCS #11 Baseline and Extended Provider (see PKCS #11 Cryptographic Token Interface Profiles Version 2.40, 16-Sep-2014, OASIS Committee Specification 01, http://docs.oasis-open.org/pkcs11/pkcs11-profiles/v2.40/cs01/pkcs11-profiles-v2.40-cs01.doc).

An introduction to this product can also be found at: P6R's PKCS 11 Provider, https://www.p6r.com/articles/2014/11/22/p6rs-pkcs-11-provider/.

P6R's PKCS 11 client follows the standards defined in the following documents.

1) OASIS, PKCS #11 Cryptographic Token Interface Base Specification Version 2.40, OASIS Standard, 14 April 2015, http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.pdf

2) OASIS, PKCS#11 Cryptographic Token Interface Current Mechanisms Specification Version 2.40, OASIS Standard, 14 April 2015, http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/os/pkcs11-curr-v2.40-os.html

3) OASIS, PKCS#11 Cryptographic Token Interface Historical Mechanisms Specification Version 2.40, OASIS Standard, 14 April 2015, http://docs.oasis-open.org/pkcs11/pkcs11-hist/v2.40/os/pkcs11-hist-v2.40-os.html

4) OASIS, OASIS, PKCS #11 Cryptographic Token Interface Usage Guide Version 2.40, Committee Note 02, 16 November 2014, http://docs.oasis-open.org/pkcs11/pkcs11-ug/v2.40/pkcs11-ug-v2.40.html

Reference 1 above defines and describes the PKCS 11 API in detail and should be used by any programmer using this library. The sections below list all limitations, subsets, and any differences from the official standard caused by limitations of the respective tokens. Reference 4 above also provides in explainations of several key parts of the PKCS #11 standard, such as its security model. The programmer is encouraged to familiar themselves with both of these references.

Includes

This library ships with the standard set of PKCS 11 Version 2.40 ".h" files as defined by the OASIS PKCS 11 Technical committee. These include the files pkcs11.h, pkcs11f.h, and pkcs11t.h. The pkcs11p6r.h file contains P6R vendor defined extensions. The file p6tokenimpl.h defines our token plugin interface for 3rd party tokens.

Note, the pkcs11.h file is meant to be slightly modified for the particular library and platform and we have made such modifications for use with our library.

KMIP Token

The KMIP token uses the facilities of a remote KMIP server to implement the features of the PKCS 11 Version 2.40 API. A KMIP token is defined by a set of configuration parameters defined in the p6pkcs11.conf file (see Section "Basic Configuration Parameters"). This token type uses P6R's Secure KMIP Client (SKC) SDK (see https://www.p6r.com/software/skc.html) to communicate with the defined KMIP servers. As of this writing, SKC works with all known commercially available KMIP servers. Our PKCS11 library allows the definition of any number of KMIP tokens all pointing to the same or different KMIP servers.

The KMIP token has the following limitations with object attributes. CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_UNWRAP, and CKA_DERIVE CANNOT be changed after an object (i.e., key, certificate, data, domain parameters) is created. This is because the KMIP protocol does not allow a client to modify the KMIP equivalent attributes after a KMIP object is created. However, this token implementation does support the modification of a CKO_DATA object’s CKA_VALUE attribute after the object has been created on a KMIP server.

If logging is turned on (see the Basic Configuration Parameters section below), then a directory will be created under the defined log path with the KMIP server's fully qualified domain (FQDN) name as the directory name (e.g., "../log/kmip01.corp.p6r.com" is created). Under the FQDN directory another directory is also created with the following format: "p6pkcs11-slot-X", where 'X' is replaced with the slot number starting at zero.

The following is a list of all supported PKCS 11 functions: C_Initialize, C_Finalize, C_GetInfo, C_GetFunctionList, C_GetSlotList, C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, C_GetMechanismInfo, C_InitToken, C_InitPIN, C_SetPIN, C_OpenSession, C_CloseSession, C_CloseAllSessions, C_GetSessionInfo, C_Login, C_Logout, C_CreateObject, C_CopyObject, C_DestroyObject, C_GetAttributeValue, C_SetAttributeValue, C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal, C_GenerateKey (not including domain parameters), C_GenerateKeyPair, C_SeedRandom, C_GenerateRandom, C_SignInit, C_Sign, C_SignUpdate, C_SignFinal, C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal, C_EncryptInit, C_Encrypt, C_EncryptUpdate, C_EncryptFinal, C_DecryptInit, C_Decrypt, C_DecryptUpdate, C_DecryptFinal, C_DigestInit, C_Digest, C_DigestUpdate, C_DigestKey, C_DigestFinal, C_WrapKey, C_UnwrapKey, and C_DeriveKey.

This token supports the following PKCS 11 objects: CKO_DATA, CKO_CERTIFICATE, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_SECRET_KEY, and CKO_DOMAIN_PARAMETERS.

Note, that not all KMIP servers will support the C_UnwrapKey function. In some cases, the KMIP token will detect this and then return the error code CKR_FUNCTION_NOT_SUPPORTED. In other cases, the C_UnwrapKey call will succeeded but subsequent attempts to retrieve the unwrapped key via calls to C_GetAttributeValue will fail, since the key remains in its wrapped format on the KMIP server.

Note, that not all KMIP servers support streaming operations such as C_EncryptUpdate, C_EncryptFinal, C_DecryptUpdate, C_DecryptFinal, C_DigestUpdate, C_DigestKey, C_DigestFinal. These streaming operations where added to KMIP 1.3 and are optional. When a server does not support these, or the KMIP version in use is not 1.3, then the error code CKR_FUNCTION_NOT_SUPPORTED will be returned for these PKCS 11 functions. In addition, our KMIP token uses several features that where defined starting with KMIP 1.2. Using a KMIP server without adaquate KMIP 1.2 support will disable several PKCS11 features.

The KMIP token does not support any of the following attributes to be passed in as part of the pTemplate parameter of the C_FindObjectsInit API call: CKA_VALUE, CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_EC_PARAMS, and CKA_EC_POINT. If any of these attributes are used C_FindObjectsInit will return the CKR_ARGUMENTS_BAD error.

Currently, C_WrapKey ignores the CKA_WRAP_TEMPLATE attribute, and C_UnwrapKey ignores the CKA_UNWRAP_TEMPLATE attribute. These should be supported in the near future.

For the CKM_RSA_PKCS_KEY_PAIR_GEN mechanism C_GenerateKeyPair() only works if the attribute CKA_PUBLIC_EXPONENT is not included in the call. Thus for the KMIP token RSA key generation only needs the CKA_MODULUS_BITS attribute.

The implementation of C_CopyObject will copy keys, certificates, data objects, and domain parameter objects. In addition, the pTemplate parameter to the C_CopyObject function supports the following attributes: CKA_TOKEN, CKA_PRIVATE, CKA_ID, CKA_SUBJECT, CKA_MODIFIABLE, CKA_DESTROYABLE, CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_START_DATE, CKA_END_DATE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, CKA_VERIFY, CKA_DERIVE, CKA_WRAP, CKA_UNWRAP, CKA_VERIFY_RECOVER, CKA_SIGN_RECOVER, and CKA_PUBLIC_KEY_INFO. The use of any other attributes will result in a CKR_TEMPLATE_INCONSISTENT returned.

The following default attribute values are used if the calling application does not define a value:

The KMIP token allows PIN values to contain any valid UTF8 character just as defined by the PKCS#11 standard (Section 5.5, C_InitToken).

Software Token

P6R's software token (or "soft token") uses P6R’s cryptographic API and Keystore to implement the features of the PKCS 11 Version 2.40 API. Both the cryptographic API and Keystore are included as part of the SKC product. Our PKCS 11 library allows the definition of any number of Software tokens where each token gets its own separate secure Keystore to manage PKCS 11 objects (e.g,. keys, certificates, domain parameters, data). P6R’s cryptographic API is a C++ object wrapper around OpenSSL’s C language API.

The location of each token's keystore id defined in configuration (see the Basic Configuration Parameters section below). The keystore's file created follows the format: "p6pkcs11-slot-X" where 'X' is replaced with the slot number starting at zero. The file 'p6pkcs11-slot-X.sig' is also created as long as the keystore in use is a local database.

The following is a list of all supported PKCS 11 functions: C_Initialize, C_Finalize, C_GetInfo, C_GetFunctionList, C_GetSlotList, C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, C_GetMechanismInfo, C_InitToken, C_InitPIN, C_SetPIN, C_OpenSession, C_CloseSession, C_CloseAllSessions, C_GetSessionInfo, C_Login, C_Logout, C_CreateObject, C_CopyObject, C_DestroyObject, C_GetAttributeValue, C_SetAttributeValue, C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal, C_GenerateKey (not including domain parameters), C_GenerateKeyPair, C_GenerateRandom, C_SignInit, C_Sign, C_VerifyInit, C_Verify, C_EncryptInit, C_Encrypt, C_EncryptUpdate, C_EncryptFinal, C_DecryptInit, C_Decrypt, C_DecryptUpdate, C_DecryptFinal, C_DigestInit, C_Digest, C_DigestUpdate, and C_DigestFinal.

This token supports the following PKCS 11 objects: CKO_DATA, CKO_CERTIFICATE, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, and CKO_SECRET_KEY.

The Software token does not support any of the following attributes to be passed in as part of the pTemplate parameter of the C_FindObjectsInit API call: CKA_VALUE, CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_EC_PARAMS, and CKA_EC_POINT. If any of these attributes are used C_FindObjectsInit will return the CKR_ARGUMENTS_BAD error.

The following default attribute values are used if the calling application does not define a value:

* CKA_TOKEN - CK_FLASE
* CKA_DERIVE - CK_FALSE (for CKO_SECRET, CKO_PUBLIC, CKO_PRIVATE keys)
*

The KMIP token allows PIN values to contain any valid UTF8 character just as defined by the PKCS#11 standard (Section 5.5, C_InitToken).

Other Tokens

A third party can create their own token types by implementing the p6tokenimpl.h interface in a P6R component.

Unsupported, Limitations and Defaults

The following are unsupported PKCS 11 features of P6R's KMIP and Software tokens and do not define any limits on third party provided tokens.

The following object attributes are unsupported in the current release: CKA_PRIME_BITS, CKA_SUBPRIME_BITS, CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE, CKA_HW_FEATURE_TYPE, CKA_PIXEL_X, CKA_PIXEL_Y, CKA_RESOLUTION, CKA_CHAR_ROWS, CKA_CHAR_COLUMNS, CKA_COLOR, CKA_BITS_PER_PIXEL, CKA_CHAR_SETS, CKA_ENCODING_METHODS, CKA_MIME_TYPES, CKA_MECHANISM_TYPE, CKA_REQUIRED_CMS_ATTRIBUTES, CKA_DEFAULT_CMS_ATTRIBUTES, CKA_SUPPORTED_CMS_ATTRIBUTES, CKA_RESET_ON_INIT, and CKA_HAS_RESET.

The following objects are unsupported in the current release for the KMIP and Software tokens: CKO_HW_FEATURE, CKH_MONOTONIC_COUNTER, CKH_CLOCK, and CKH_USER_INTERFACE.

The CKA_TOKEN attribute defaults to false, and the CKA_PRIVATE attribute defaults to true if not defined in a template to an API function for the KMIP and Software tokens.

A Secure Implementation

P6R’s Provider allows any number of slots to be defined and in each slot either type of token can be configured. For example, it is possible to have a PKCS 11 installation that points to several different KMIP servers and several different software token instances each separate from the others. All slots and tokens are defined via a the p6pkcs11.conf configuration file. This configuration file allows the definition of any P6R or customer specific behavior since the PKCS 11 interface is fixed by the OASIS Technical Committee. All keys and certificates required to communicate with a KMIP server or to encrypt/sign a Keystore’s contents are themselves securely stored in a PKCS 11 wide Keystore once the library is initialized.

Supported Mechanisms

The current KMIP token library supports the following mechanisms: CKM_AES_KEY_GEN, CKM_CAST5_KEY_GEN, CKM_BLOWFISH_KEY_GEN, CKM_TWOFISH_KEY_GEN, CKM_CAMELLIA_KEY_GEN, CKM_RC2_KEY_GEN, CKM_RC4_KEY_GEN, CKM_RC5_KEY_GEN, CKM_IDEA_KEY_GEN, CKM_SKIPJACK_KEY_GEN, CKM_DES_KEY_GEN, CKM_DES3_KEY_GEN, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_EC_KEY_PAIR_GEN, CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS, CKM_DSA_SHA1, CKM_DSA_SHA224, CKM_DSA_SHA256, CKM_ECDSA_SHA1, CKM_AES_CBC, CKM_BLOWFISH_CBC, CKM_BLOWFISH_CBC_PAD, CKM_TWOFISH_CBC, CKM_CAMELLIA_ECB, CKM_CAMELLIA_CBC, CKM_DES_ECB, CKM_DES_CBC, CKM_DES_CBC_PAD, CKM_IDEA_ECB, CKM_IDEA_CBC_PAD, CKM_CAST5_ECB, CKM_CAST5_CBC, CKM_CAST5_CBC_PAD, CKM_AES_OFB, CKM_AES_CFB8, CKM_AES_CFB64, CKM_AES_CFB128, CKM_SHA_1_HMAC, CKM_SHA224_HMAC, CKM_SHA256_HMAC, CKM_SHA384_HMAC, CKM_SHA512_HMAC, CKM_AES_CMAC, CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512, CKM_SHA512_224, CKM_SHA512_256, CKM_MD2, CKM_MD5, CKM_RIPEMD160, CKM_RC2_ECB, CKM_RC2_CBC, CKM_RC2_CBC_PAD, CKM_DES3_ECB, CKM_DES3_CBC, CKM_RC4, CKM_SKIPJACK_ECB64, CKM_SKIPJACK_CBC64, CKM_SKIPJACK_OFB64, CKM_SKIPJACK_CFB64, CKM_SHA256_KEY_DERIVATION, and CKM_RSA_PKCS_OAEP.

If a specific KMIP server does not support one of the above mechanisms (e.g., CKM_EC_KEY_PAIR_GEN), then it can be "disabled" via an entry in the p6pkcs11.conf file for the specific slot (see the description of the tokenDisabledMechs configuration parameter in Section "Basic Configuration Parameters").

The current Software token library supports the following mechanisms: CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS, CKM_DSA_SHA1, CKM_DSA_SHA224, CKM_DSA_SHA256, CKM_ECDSA_SHA1, CKM_SHA_1_HMAC, CKM_SHA224_HMAC, CKM_SHA256_HMAC, CKM_SHA384_HMAC, CKM_SHA512_HMAC, CKM_BLOWFISH_CBC, CKM_DES_ECB, CKM_DES_CBC, CKM_CAST5_ECB, CKM_CAST5_CBC, CKM_IDEA_ECB, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_OFB, CKM_AES_CFB8, CKM_AES_CFB64, CKM_AES_CFB128, CKM_AES_CTR, CKM_DES3_ECB, CKM_DES3_CBC, CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512, CKM_SHA512_224, CKM_SHA512_256, CKM_MD2, CKM_MD5, and CKM_RIPEMD160.

Vendor Extensions

P6R defines the following vendor defined attributes:

* Purpose: to allow PKCS 11 objects to be placed into collections
* Data Type: RFC 2279 string
* MUST be specified when object is created with C_CreateObject.
* MUST be specified when object is created with C_GenerateKey or C_GenerateKeyPair.
*
* CKA_P6R_GROUP 0x80001000UL
*
*
* Purpose: to allow a user to associate whatever data they want to an object
* Data Type: Byte Array
* Can be created and modified at any time
*
* CKA_P6R_EXT1 0x80001002UL
*

The purpose of this extension is to provide basic support for KMIP groups and it maps into the KMIP "Object Group" attribute. Without the CKA_P6R_GROUP attribute defined the standard "default" group is used. P6R's Keystore has the concept of namespaces. These are similar to groups in that they provide collections of objects. When CKA_P6R_GROUP is used for the Software token its value is mapped into the Keystore's namespace parameter. Without the CKA_P6R_GROUP attribute defined the Software token uses "PKCS11" namespace by default.

P6R defines the following vendor defined method:

P6R_DestroyToken() frees all contents in the token and disables its containing slot. This method is added so that a PKCS 11 application can remove a token programmatically.

* extern CK_DECLARE_FUNCTION(CK_RV, P6R_DestroyToken)
* (
* CK_SLOT_ID slotID, // ID of the token's slot
* CK_UTF8CHAR_PTR pPin, // the SO's initial PIN
* CK_ULONG ulPinLen // length in bytes of the PIN
* );
*

Only the SO (i.e., Security Officer) can make this call. The call cannot be made on a token that currently has any in-progress sessions (otherwise the CKR_SESSION_EXISTS error is returned). This function deletes all the stored content on a token and disables the token and slot from use. The slot is disabled by writing the slot identifier into the file specified in the "disabled" configuration parameter (see Section "Basic Configuration Parameters" below). Once a slot is disabled it will not be able to be used or (re-)initialized. Also calls to C_GetSlotInfo() and C_GetTokenInfo() will not return previous slot/token information.

To reuse the slot the SO must enable the slot again by removing its slot identifier from the file defined by the "disabled" configuration parameter, and then redefine (as desired) its token configuration in the p6pkcs11.conf file. Once completed the token can then be initialized as if new.

Return values: CKR_CRYPTOKI_NOT_INITIALIZED, CKR_ARGUMENTS_BAD, CKR_SLOT_ID_INVALID, CKR_SESSION_EXISTS, CKR_PIN_INCORRECT, CKR_DEVICE_ERROR, CKR_GENERAL_ERROR, CKR_FUNCTION_FAILED, CKR_OK

Java Security Provider

Java supports PKCS 11 as a possible security provider (see https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html). With P6R's KMIP token a Java application is able to use KMIP though our PKCS 11 library once it is configured as a security provider. See PKCS 11 examples 11, 12, 13 for working examples of using our PKCS 11 library as a Java Security Provider. These examples include all the details for configuration steps required to run our library as a security provider on Linux and Windows.

One of these steps involves configuring the SunPKCS11 wrapper by editing the java.security file,

Defining P6R's PKCS 11 library as a security provider on Windows

* # On our windows system the java.security file was at C:\Program Files\Java\jdk1.8.0_65\jre\lib\security
* # List of providers and their preference orders (see above):
* #
* security.provider.1=sun.security.provider.Sun
* security.provider.2=sun.security.rsa.SunRsaSign
* security.provider.3=sun.security.ec.SunEC
* security.provider.4=com.sun.net.ssl.internal.ssl.Provider
* security.provider.5=com.sun.crypto.provider.SunJCE
* security.provider.6=sun.security.jgss.SunProvider
* security.provider.7=com.sun.security.sasl.Provider
* security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
* security.provider.9=sun.security.smartcardio.SunPCSC
* security.provider.10=sun.security.mscapi.SunMSCAPI
* security.provider.11=sun.security.pkcs11.SunPKCS11 c:\\PKCS11\\p6rpkcsll.cfg
*

The full file path above is just an example of where to place the SunPKCS11 required ".cfg" file.

Defining P6R's PKCS 11 library as a security provider on Centos 6

* # On our Linux Centos6 the java.security file was at /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.77-0.b03.el6_7.x86_64/jre/lib/security
* # List of providers and their preference orders (see above):
* #
* security.provider.1=sun.security.provider.Sun
* security.provider.2=sun.security.rsa.SunRsaSign
* security.provider.3=com.sun.net.ssl.internal.ssl.Provider
* security.provider.4=com.sun.crypto.provider.SunJCE
* security.provider.5=sun.security.jgss.SunProvider
* security.provider.6=com.sun.security.sasl.Provider
* security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
* security.provider.8=sun.security.smartcardio.SunPCSC
* security.provider.9=sun.security.pkcs11.SunPKCS11 /home/mjoseph/PKCS11/p6rpkcs11.cfg
*

Another step is to properly configure the ".cfg" file that the SunPKCS11 expects. As an example, below is the p6pkcs11.cfg file we used on Centos 6. Note, that the "library" property contains the full path to a directory where our PKCS 11 library has been set up to run out of. Please refer to the Oracle SunPKCS11 documentation concerning the other aspects of this configuration file.

* name = P6RPKCS11
* library=/home/mjoseph/skc-2016.2.16389/examples/kmip/kmip-1/linux-DBG64/libp6pkcs11.so
* description = P6R PKCS11 Provider 2016.2
* slot = 0
* attributes(generate,CKO_PRIVATE_KEY,*) = {
* CKA_DECRYPT=true
* CKA_SIGN = true
* CKA_VERIFY = true
* CKA_TOKEN = true
* CKA_PRIVATE = true
* }
*
* attributes(generate,CKO_PUBLIC_KEY,*) = {
* CKA_ENCRYPT=true
* CKA_SIGN = true
* CKA_VERIFY = true
* CJA_TOKEN = true
* CKA_PRIVATE = true
* }
*
* attributes(generate,CKO_SECRET_KEY,*) = {
* CKA_ENCRYPT = true
* CKA_DECRYPT = true
* CKA_TOKEN = true
* CKA_PRIVATE = true
* CKA_EXTRACTABLE = true
* }
*

And of course to use the KMIP token it has to first be initialized. We suggest using the p6pkcs11tool command line tool for this but it can also be done in a C program using the PKCS 11 API directly.

PrimeKey's SignServer Integration

The KMIP token can be configured to work with PrimeKey's SignServer (https://www.signserver.org/). All keys are stored in the KMIP server and all encryption performed on a KMIP server. This integration requires a KMIP server with KMIP protocol version 1.3 and greater with streaming capability supported.

Basic Configuration Parameters

A slot is defined by a section in the p6pkcs11.conf file of the form: "[p6pkcs11-slot-X]". where "X" is replaced with the slot number. An example of such a configuration file with 3 slots where 2 are KMIP tokens and the 3rd is P6R's software token. Many of the configuration items match to standard slot and token information returned by the C_GetSlotInfo() and C_GetTokenInfo() PKCS 11 API functions. In addition to the configuration defined in this section, change to the p6kmip.conf file for KMIP logging is recommended (see the SKC documentation).

* [p6pkcs11-gen]
* baseKeyPath="/var/PKCS11/baseKey.txt"
* customerKeyPath="/var/PKCS11/customer1key.txt"
* keystore="/var/PKCS11/keys"
* logDir="/var/log/pkcs11"
* disabled="/var/PKCS11/disabled.txt"
* initialSessions=100
* pkcs11LibFlags=3
*
* [p6pkcs11-slots-gen]
* slotCount=5
*
* [p6pkcs11-tokens]
* UtimacoVersion220 = "{3367270E-43E6-4fed-B57A-0711FAE20CCA}"
* ThalesVersion201 = "{73BED027-BBE5-44dc-ACCE-302647D9E7BD}"
* FuturexVersion22 = "{D6EBC68A-9D3E-4998-B587-C68B6BD3169C}"
* DocuSign220 = "{3A55CD57-71DE-495a-A172-43B604C241C0}"
* SafeNetLuna = "{AB0258D5-7CC1-422a-916F-9D57F7E70808}"
* EngageBlackVault = "{64468002-9B40-45d1-94A5-A749CD8E390E}"
*
* [p6pkcs11-slot-0]
* slotDescription="KMIP SLOT1"
* slotFlags=5
* slotManufacturer="P6R"
* slotType="P6R-KMIP"
* tokenFirmwareVersion="1.60"
* tokenHardwareVersion="1.1"
* tokenKMIPCertPEM="/var/PKCS11/PKCS11/slot0/CR_P6R_cert_kmip1.pem"
* tokenKMIPInitFlags=1036
* tokenKMIPPort=5696
* tokenKMIPPrivPEM="/var/PKCS11/slot0/CR_P6R_privkey_kmip1.pem"
* tokenKMIPPrivSize=2048
* tokenKMIPRootPEM="/var/PKCS11/slot0/CR_root_kmip1.pem"
* tokenKMIPServer=interop.cryptsoft.com
* tokenKMIPMaxVersion="1.2"
* tokenKMIPUseFlags=1
* tokenManufacturer="Cryptsoft"
* tokenMaxSession="0"
* tokenModel="KMIP C Server"
* # disable mechanisms: CKM_EC_KEY_PAIR_GEN, CKM_RC4_KEY_GEN
* tokenDisabledMechs = 4160,272
*
* [p6pkcs11-slot-1]
* slotDescription="P6R's Keystore & Crypto"
* slotFlags=1
* slotManufacturer="P6R"
* slotType="P6R-keystore"
* tokenFirmwareVersion="1.00"
* tokenManufacturer="P6R"
* tokenModel="KEYSTORE 1.3"
* tokenSoftKeystore="/var/PKCS11/keystore"
*
* [p6pkcs11-slot-2]
* slotDescription="KMIP SLOT2"
* slotFlags=5
* slotManufacturer="P6R"
* slotType="P6R-KMIP"
* tokenFirmwareVersion="1.2"
* tokenHardwareVersion="1.1"
* tokenKMIPCertPEM="/var/PKCS11/slot2/LP_dev_kmip2.cer"
* tokenKMIPInitFlags=1036
* tokenKMIPsslOptions=612
* tokenKMIPPort=5696
* tokenKMIPMaxVersion="1.2"
* tokenKMIPPrivPEM="/var/PKCS11/slot2/LP_dev_kmip2.key"
* tokenKMIPPrivSize=2048
* tokenKMIPRootPEM="/var/PKCS11/slot2/LP_dev_root_kmip2.ca"
* tokenKMIPServer=kmiptest01.p6r.com
* tokenManufacturer="LP"
* tokenMaxSession="0"
* tokenModel="LP KServer 3.0"
*
* [p6pkcs11-slot-3]
* slotType="UtimacoVersion220"
* slotFlags=5
* vendorSlotId=0
* vendorVerifyPIN=true
* vendorPreInitToken=true
*
* [p6pkcs11-slot-4]
* slotType="ThalesVersion201"
* slotFlags=5
* vendorSlotId=492971158
* vendorVerifyPIN=true
* vendorPreInitToken=true
* vendorCompat=1
*

Other possible slot and token configuration items:

* pkcs11LibFlags
* applicationCompat
* tokenDefaultGroup
* tokenKMIPconnectTimeout
* tokenKMIPsendTimeout
* tokenKMIPreceiveTimeout
* tokenKMIPMaxBufSize
* tokenKMIPInitialBufCount
* tokenKMIPGrowBufsBy
* tokenKMIPPrvKeyEncode
* tokenKMIPPubKeyEncode
* tokenKMIPSymKeyEncode
* tokenKMIPcompatibility1
* tokenKMIPAsynch
* tokenKMIPVersion
* tokenKMIPUserName
* tokenKMIPPassword
* tokenKMIPSerialNum
* tokenKMIPDeviceId
* tokenKMIPNetworkId
* tokenKMIPMachineId
* tokenKMIPMediaId
* tokenMinPinLen
* tokenMaxPinLen
* tokenKMIPsslCiphers
* tokenKMIPVerifyBytes
*

Restrictions: 1) Each KMIP token must point to a different KMIP server. A KMIP server is defined by the "tokenKMIPServer" configuration parameter and is a fully qualified domain name with an optional port (e.g., "kmiptest01.p6r.com", "kmiptest01.p6r.com:5696"). Thus each slot "contains" a unique token. Note that multiple sessions are supported for each KMIP token. This restriction also prevents one slot from re-initializing its token out from under another slot with the same KMIP token definition.

The [p6pkcs11-gen] Config Section*

This contains the following PKCS 11 wide configuration parameters:

"baseKeyPath" Config Variable (string Value)

The "baseKeyPath" configuration parameter (string value), is the symmetric key protecting the PKCS 11 keystore is to be written to after it is generated by the library. This parameter can be either a full path to the key file or just the name of the key file. If it is just a file name then it will be treated as relative to the directory the library runs out of. Essentially, this is the one key that is kept in the clear. Either this parameter OR the "customerKeyPath" parameter is defined. If both are defined, then the customerKeyPath parameter will be used.

"customerKeyPath" Config Variable (string Value)

The "customerKeyPath" configuration parameter (string value), is the symmetric key protecting the PKCS 11 keystore. The difference between this parameter and the "baseKeyPath" is that the baseKeyPath key is generated by this command line tool while the customerKeyPath key is provided by the customer. The customer must provide an AES 256 bit PEM encoded file.

"keystore" Config Variable (string value)

The "keystore" configuration parameter (string value), is optional and can be either the full path to a directory where the PKCS 11 library wide keystore is to be created or a database URI of the standard for: "postgresql8://..." (see Keystore documentation). When this parameter is not provided then a default location is used. Otherwise, when using the full path to a local directory then a Sqlite database will be used. This keystore holds all the keys and certificates used to communicate to KMIP servers and all keys used to protect all other keystores created for software tokens.

"logdir" Config Variable (string value)

The "logDir" configuration parameter (string value), is optional and when not provided a default location is used. Otherwise, the parameter must be a full path to the diretory where PKCS 11 log statements output should be written to.

"disabled" Config Variable (string value)

The "disabled" configuration parameter (string value), is the full path to a file to create that holds all disabled slots as a result of executing the P6R_DestroyToken() extension method. The path must be to a writtable directory. This parameter is optional and is only required if the P6R_DestroyToken() method is to be used.

"initialSessions" Config Variable (positive numeric value)

The "initialSessions" configuration paramter (positive numeric value), is optional and defines the number of possible, concurrent PKCS 11 library wide sessions to start with. This number will be used to pre-allocate sonme of the client memory to support those initial number of sessions. Note that the total number of open sessions is dynamic and will grow as need and as memory permits. This paramter defaults to 200. Note that each active session requires a chunk of memory to maintain its state.

"pkcs11LibFlags" Config Variable (positive numeric value)

The "pkcs11LibFlags" configuration parameter (numeric bit mask), is optional and defines special library wide handling or features. Represented as an unsigned integer. The current set of valid bit flags are:

* 0x0001 for Recover PKCS11 keystore from Signature Mismatch error (i.e., 0x80040011),
* 0x0002 force PKCS ll library to use internally created multi-threading locking if no locking already set.
* 0x0004 return CKR_OK for extra calls to C_Initialize instead of returning the error code CKR_CRYPTOKI_ALREADY_INITIALIZED.
* This puts the PKCS 11 library in reference counting mode. This means that each call to C_Initialize must have a matching
* call to C_Finalize and that only the last call to C_Finalize will actually do anything. This does not match the defined
* PKCS 11 standard behavior.
*

(For example, if all 3 flags where set then "pkcs11LibFlags=7" would be the correct value.)

The [p6pkcs11-slots-gen] Config Section

The "[p6pkcs11-slots-gen]" section contains the following PKCS 11 configuration parameters global across all defined slots:

"slotCount" Config Variable (positive decimal integer)

The "slotCount" configuration paramter (positive numeric value), defines the number of slots defined by the p6pkcs11.conf file. Each defined slot gets its own configuration file section such as "[p6pkcs11-slot-X]" where 'X' is replaced with a positive integer starting at zero. With a slotCount of 3 the following configuration file sections should exist: "[p6pkcs11-slot-0]", "[p6pkcs11-slot-1]", "[p6pkcs11-slot-2]".

The [p6pkcs11-tokens] Config Section

The "[p6pkcs11-tokens]" section contains third party token implementations via the p6tokenimpl.h interface definition.

<tokenname> Config Variable (string GUID)

Each item in this section consists of a token "name" with its component GUID. For example: UtimacoVersion220 = "{3367270E-43E6-4fed-B57A-0711FAE20CCA}", defines a token named "UtimacoVersion220" with a component GUID of "{3367270E-43E6-4fed-B57A-0711FAE20CCA}". This section can contain any number of token implemenation definitions. In the configuration example above, the "[p6pkcs11-slot-3]" section defines its token implementation via the parameter: slotType="UtimacoVersion220". Several 3rd party tokens are included in the SKC product which are implemented in the component: p6pkcs11tokens.dll on Windows, and p6pkcs11tokens.so on Linux files.

When the "[p6pkcs11-slot-X]" section defines a Software token the following configuration parameters apply:

The "slotDescription" configuration parameter (string value), maps to the "slotDescription" field of the CK_SLOT_INFO PKCS 11 API structure. This field is limited to a maximum of 64 characters.

The "slotFlags" configuration parameter (positive numeric value), maps to the "flags" field of the CK_SLOT_INFO PKCS 11 API structure. Valid values of this flag field are defined in the specification: PKCS #11 Cryptographic Token Interface Base Specification Version 2.40, Section 3.2 Slot and token types, Table 5, Slot Information Flags. For example, these values for PKCS#11 Version 2.40::

* CKF_TOKEN_PRESENT 0x00000001
* CKF_HW_SLOT 0x00000004
*

So for example, our KMIP token should have the value '5' for this parameter since the token is present and its a Hardware slot. However, our software token should only have a value of '1' for this parameter.

The "slotManufacturer" configuration parameter (string value), maps to the "manufacturerID" field of the CK_SLOT_INFO PKCS 11 API structure. This field is limited to a maximum of 32 characters.

The "slotType" configuration parameter (string value), this is a P6R defined configuration value which defines the token type that runs out of the defined slot. Current valid P6R token names are: { "P6R-keystore", "P6R-KMIP" } where the first value is used to define a Software token and the second value is used for a KMIP token. This parameter can be used to specify a 3rd party token implementation defined in the "[p6pkcs11-tokens]" section. The token name indicates which token type is to be used by the slot and the PKCS 11 library ensures that the proper implementation is used.

The "applicationCompat" configuration parameter (positive numeric value), is an optional parameter. It is a bit mask defining behavior that the calling application expects of the PKCS 11 library for the application to operate properly. The following values are currently defined: { 0 - no special actions required, 1 - create a default value for CKA_LABEL for calls to C_CreateObject(), C_GenerateKey(), and C_GenerateKeyPair() if no value of CKA_LABEL is provided }. This feature will work in both the KMIP and Software tokens.

The "tokenFirmwareVersion" configuration parameter (string value), maps to the "firwareVersion" field of the CK_TOKEN_INFO PKCS 11 API structure. For software tokens we use this field to define the version of the PKCS 11 library itself since the Software token is built into the library.

The "tokenManufacturer" configuration parameter (string value), maps to the "manufacturerID" field of the CK_TOKEN_INFO PKCS 11 API structure. For software tokens we use this field to define P6R as the manufacturer.

The "tokenModel" configuration parameter (string value), maps to the "model" field of the CK_TOKEN_INFO PKCS 11 API structure. Again for software tokens we use this field to define the value "KEYSTORE 1.3".

The "tokenSoftKeystore" configuration parameter (string value), is optional and can either the full path to a directory where the slot's keystore is to be created or a database URI of the standard for: "postgresql8://..." (see Keystore documentation). When this parameter is not provided then a default location is used. Otherwise, When using the full path to a local directory then a Sqlite database will be used. This keystore holds all the PKCS 11 defined objects for this token (e.g., CKO_SECRET_KEY, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_CERIFICATE, CKO_DOMAIN_PARAMTERS, CKO_DATA).

The "tokenDefaultGroup" configuration parameter (string value), can be used instead of the CKA_P6R_GROUP vendor attribute extension. For the KMIP Token this parameter maps to the KMIP "Object Group" attribute. For the Software Token is parameter maps to the P6R's Keystore namespace parameter. When not specified the library uses "PKCS11" as the built in default group.

The "tokenMinPinLen" configuration parameter (positive numeric value), defines the smallest number of bytes of length that a PIN is allowed to be for a token. The defailt value is 8.

The "tokenMaxPinLen" configuration parameter (positive numeric value), defined the largest number of bytes of length that a PIN is allowed to be for a token. The default value is 25.

When the "[p6pkcs11-slot-X]" section defines a KMIP token the following configuration parameters apply:

slotDescription, slotFlags, slotManufacturer, slotType, applicationCompat, tokenFirmwareVersion, tokenManufacturer, tokenModel, tokenDefaultGroup, tokenMinPinLen, and tokenMaxPinLen all are the same as described above.

The "tokenHardwareVersion" configuration parameter (string value), maps to the "hardwareVersion" field of the CK_TOKEN_INFO PKCS 11 API structure. This and the tokenFirmwareVersion can be used to define versions of the remote KMIP server.

The "tokenMaxSession" configuration parameter (string value), maps to both the "ulMaxSessionCount" and "ulMaxRwSessionCount" fields of the CK_TOKEN_INFO PKCS 11 API structure. If this string is set to "-1", then the default value of 100 is used for both of these fields. If this string is set to "0" that maps to the constant CK_EFFECTIVELY_INFINITE, then the only limit that will be checked is the maximum number of total sessions that the PKCS 11 library can handle at once.

The "tokenKMIPServer" configuration parameter (string value), is the fully quallified domain name (FQDN) of the remote KMIP server. It is passed to P6R's Secure KMIP Client (SKC) library.

The "tokenKMIPPort" configuration parameter (positive numeric value), is optional with the default value of 5696 defined. It is passed to the SKC library.

The "tokenKMIPMaxVersion" configuration parameter (string value), this parameter defines the maximum KMIP protocol that PKCS 11 should use to communicate with a remote KMIP server. This is an optional field and if not set the code will select the largest supporting protocol version. This library automaically calls the KMIP Discover Version operation to select a protocol version to use.

The "tokenKMIPVersion" configuration parameter (string value), is optional and defines the KMIP protocol version that PKCS 11 should use to start communicatation with a remote KMIP server. This has a default value of "1.2". If both this paramter and tokenKMIPMaxVersion are set then this paramter will be used to start a session with a KMIP server and then may be changed by the value defined in tokenKMIPMaxVersion.

The "tokenKMIPsslOptions" configuration parameter (numeric bit mask), is optional and maps to the SKC setSSLOptions( const P6WCHAR* pCiphers, P6SECURESOCKETFLAGS fSecureFlags ) API call's fSecureFlags parameter (see file p6kmpclient.h). This allows the caller to customize how it makes an TLS connection to a remote KMIP server. The default setting for this parameter is (P6SSF_METHOD_NEGOTIATE | P6SSF_SECURE_CLIENT | P6SSF_SECURE_CLIENT_AUTH | P6SSF_LOG_X509SUBJECTLOOKUPS) (see file p6net.h).

The "tokenKMIPsslCiphers" configuration parameter (string value), is optional and is used to override the default library's TLS cipher settings. This string contains the OpenSSL cipher command (see https://www.openssl.org/docs/man1.0.2/apps/ciphers.html). If not defined then the following secure default will be used: "TLSv1+HIGH:TLSv1.2+HIGH:!SSLv2:!aNULL:!eNULL:!3DES:@STRENGTH" which enables SSLv3 and TLSv1, disables SSLv2, disables ciphers that do not use authentication, disables 3DES, and prefers the strongest ciphers fist.

The "tokenKMIPInitFlags" configuration parameter (numeric bit mask), is optional and maps to the SKC initialize( P6KMIPFLAGS flags, p6IKeystore* pCerts, P6KMIP_PREF preferences ) API calls's flags parameter (see file p6kmipclient.h. This has the default value of P6KMIPFLG_NOFLAGS. Note, that this parameter is how the user can control KMIP message logging (e.g., using the P6KMIPFLG_TRACE_MSGS flag value). See SKC documentation on the possible values for this parameter.

The "tokenKMIPCertPEM" configuration parameter (string value), is the full path to a client side certificate (in PEM format) that was issued by a KMIP server to allow a KMIP client to authenticate itself. This certificate is copied into the PKCS 11 wide keystore for use by SKC to create a TLS connection to a KMIP server.

The "tokenKMIPPrivPEM" configuration parameter (string value), is the full path to the client's private key (in PEM format) that was issued by a KMIP server to allow a KMIP client to authenticate itself. This key is copied into the PKCS 11 wide keystore for use by SKC to create a TLS connection to a KMIP server.

The "tokenKMIPPrivSize" configuration parameter (positive numeric value), is the number of bits of the private key defined by the tokenKMIPPrivPEM configuration parameter.

The "tokenKMIPRootPEM" configuration parameter (string value), is the full path to the KMIP server's root certificate that was provided by a KMIP server to allow the Secure KMIP Client to create a TLS connection to the remote KMIP server.

The "tokenKMIPconnectTimeout", "tokenKMIPsendTimeout", "tokenKMIPreceiveTimeout", "tokenKMIPMaxBufSize", "tokenKMIPInitialBufCount", "tokenKMIPGrowBufsBy", "tokenKMIPPrvKeyEncode", "tokenKMIPPubKeyEncode", "tokenKMIPSymKeyEncode", and "tokenKMIPcompatibility1" configuration parameters (positive numeric values), are all optional and maps to the SKC initialize( P6KMIPFLAGS flags, p6IKeystore* pCerts, P6KMIP_PREF preferences ) API calls's P6KMIP_PREF parameter (see file p6kmipclient.h and SKC documentation). PKCS 11 library has a reasonable set of default values for each parameter.

The "tokenKMIPAsynch" configuration paramter (positive numeric value), is optional and maps to the SKC initialize API call's P6KMIP_PREF parameter (see file p6kmipclient.h and SKC documentation). This field is used to enable / disable the SKC client asynchronous KMIP request option.

The "tokenKMIPUseFlags" configuration parameter (numeric bit mask), allows the user to modify how the KMIP client uses the KMIP protocol. If not defined the client has reasonable internal defaults. The following values can be used to create a bit mask value for this parameter.

* KMIP_USE_KEKKEYROLE - this enables the automatic setting of the "KEK" Key Role Type in the Cryptographic Parameters attribute
* for any keys that may be used in wrapping.
*
* KMIP_USE_LABELTONAME - this make the CKA_LABEL PKCS#11 attribute to be mapped to the KMIP attribute 'Name'. This is not
* default behavior since CKA_LABEL does not have to hold a unique value while the KMIP Name attribute does.
*
* KMIP_USE_SEEALLKEYS1 - default behavior is for the PKCS#11 KMIP token to only allow the caller to see keys and objects created by this library.
* This default bahavior prevents accidental deletion of pre-existing keys and other KMIP objects. This flag removes that restriction.
*
* KMIP_USE_P11LIKE - for KMIP 1.4 and greater use the KMIP attributes "Sensitive", "Always Sensitive", "Extractable", and "Never Extractable" instead of the
* KMIP custom attributes the library uses for easiler KMIP protocol versions (e.g., "x-P6R-Cryptoki-SENSITIVE"). These PKCS#11 like attributes where
* added to KMIP to match PKCS#11 functionality. For applications that already use the custom attributes there is a feature in the p6pkcs11tool command
* line tool (TBD) that performs conversion from the old custom to the new KMIP 1.4 defined attributes. Please perform a conversion before using this setting.
* Applications should only use this setting if they are sure their application will only run with KMIP protocol version 1.4 and greater.
*
* KMIP_USE_KEKKEYROLE = 0x00000001
* KMIP_USE_LABELTONAME = 0x00000002
* KMIP_USE_SEEALLKEYS1 = 0x00000004
* KMIP_USE_P11LIKE = 0x00000008
*

The "tokenKMIPUserName" and "tokenKMIPPassword" configuration parameters (string values), are optional and map to KMIP user credentials (see SKC documentation p6kmipclient.h P6KMIP_CREDENTIAL definition).

The "tokenKMIPPassword", "tokenKMIPSerialNum", "tokenKMIPDeviceId", "tokenKMIPNetworkId", "tokenKMIPMachineId", and "tokenKMIPMediaId" configuration parameters (string values), are optional and map to KMIP device credentials (see SKC documentation p6kmipclient.h P6KMIP_CREDENTIAL definition).

The "tokenKMIPVerifyBytes" configuration paramter (positive numeric value), is optional and defines the number of memory that can be allocated per token session to support the KMIP implementation of C_VerifyUpdate and C_VerifyFinal (i.e., streaming signature verification). Because PKCS#11 and KMIP APIs have a basic incompatability our implementation has to cache all they bytes passed into C_VerifyUpdate to be passed to the KMIP server only during the C_VerifyFinal call. The default value of zero is unlimited. The units are in mega-bytes so that a value of '10' means 10,000,000 bytes.

The "tokenDisabledMechs" configuration parameter (list of positive integers base 10) contains a set of PKCS 11 mechanism identifier constants (e.g., 4160 for the constant CKM_EC_KEY_PAIR_GEN, and 272 CKM_RC4_KEY_GEN [see pkcs11t.h]) which are to be disabled for the token. Here disabled means that the mechanisms will not be provided in the output of the C_GetMechanismList() and C_GetMechanismInfo() calls. This configuration item is optional.

When the "[p6pkcs11-slot-X]" section defines a 3rd party token the following configuration parameters apply:

The "vendorSlotId" configuration parameter (positive numeric value), is the slot identifier to be used for the 3rd party's token. This is used when the 3rd party token exposes its own PKCS#11 API and will have its own slot numbers to be mapped to.

The "vendorVerifyPIN" configuration parameter (boolean "true/false"), indicates whether the vendor's 3rd party token verifies the user PIN itself or depends on the P6R PKCS11 library to verify the user and SO PINs. The default value is "false".

The "vendorPreInitToken" configuration parameter (boolean "true/false"), indicates whether the vendor's 3rd party token has initialized its token via external means (e.g., a separate application). The default value is "false".

The "vendorFlags" optional configuration parameter (positive numeric value), is passed into the vendors implementation for the "libWibFlags" parameter of the method p6ITokenImpl::initialize( CK_RV* pRV, P6PKCS11PLUGFLAGS libWideFlags, P6BWCSTR* pTokenType ). The vendor can define their own values or use those defined in the p6tokenimpl.h file.

The "vendorCompat" (compatibility) optional configuration parameter (positive numberic value), is used to control behavior of the P6R PKCS#11 library as it interacts with 3rd party tokens. The currently defined values are: (0x0001) disable CKA_DESTROYABLE, (0x0002) disable CKA_COPYABLE. The CKA_DESTROYABLE attribute was added in the PKCS#11 Version 2.40 standard documents. PKCS#11 versions prior to V2.40 will consider this attribute as unknown. This flag disables its use in the P6R library.

Low-Level and Debug Logging Configuration

The library provides a very low-level debug logging mechanism and a higher level debug logging mechanism that allows the diagnosis of startup and other library issues. This mechanism does not log protocol related information. See the Basic Configuration Parameters section for details on configuring protocol logging. This mechanism is intended to help debug library startup and other non-protocol related issues.

Low-Level Logging

The low level logging is a failsafe log to provide diagnostics for log creation. If the debug log is not being created, then this is the place to look for information on why that may be. When the library loads, it will always create this file in the temp directory and it will be named "p6cryptoki-startup.log". On most Llinux systems it will be created the "/tmp" directory. If you system does not have a "/tmp", then it will try "/usr/tmp" and then "/var/tmp". This file is overwritten each time the library is loaded.

Debug Logging

Debug logging is enabled by placing a file in the same directory as the pksc11 shared library. When the library is first loaded and starts up, it will look for this file and if found will begin sending log output to it. The filename itself controls what is logged. For example, if the pkcs11 shared library is located in "/opt/product/bin" then a file named "p6cryptoki-info.log" will enable logging of "info" and "errors" level log messages into that file.

To disable logging, the pkcs11 shared library will need to be unloaded and the log file deleted or renamed to something that does not start with "p6cryptoki".

Controlling What Is Logged In The Debug Log

To change what information is logged, the log filename is changed by adding dash separated log-level qualifiers to the filename to indicate which log-levels are to be included in the log output. The allowable log-level qualifiers are "debug", "info", "warn" and "all". Errors are always logged.

The following table illustrates the naming convention that is used:

FilenameDescription
p6cryptoki.logIf no qualifiers are added, then only errors will be logged.
p6cryptoki-debug.logSince errors are always logged, this would log "debug" and "error" log messages.
p6cryptoki-info.logSince errors are always logged, this would log "info" and "error" log messages.
p6cryptoki-warn.logSince errors are always logged, this would log "warn" and "error" log messages.
p6cryptoki-all.logThis is shorthand for enabling all log-levels.
p6cryptoki-info-warn.logMultiple qualifiers can be used. Since errors are always logged, this would log "info", "warn" and "error" log messages.
P6CRYPTOKI-waRn-Info.lOgMultiple qualifiers can be used and are case insenitive. This is identical in function to the previous example.

Note that qualifiers can be specified in any order and are case-insensitive.

P6R's Command Line Tool

P6R’s PKCS 11 library also ships with a command line tool. This executable is a PKCS 11 application in that it dynamically loads our library and calls C_GetFunctionList in order to obtain the API function pointers. A user can use this command line tool to initialize a token, set the SO or User’s PIN, list all configured slots, list information on a token, generate keys, import and export some certificates and keys, and list the contents of a token. We have been using this command line tool to manage our KMIP, Software, and HPE Atalla HSM tokens.

The command line tool is an executable that can be found in the "bin" directory in a SKC release. Executing it without any parameters (or with "-h" for help) will display usage documentation showing its current set of functionality.

Utimaco HSM Integration

A Utimaco HSM can be configured to look like another token. Actually we map one slot of the Utimaco HSM into one slot of our P6R PKCS#11 library. In the example below, P6R slot number 5 is mapped to Utimaco HSM slot number 0 (see the vendorSlotId parameter).

This is easily done by the following two steps. First, define the Utimaco slot in the p6pkcs11.conf file. An example of how to do this is above in the section Basic Configuration Parameters and is repeated below:

* [p6pkcs11-tokens]
* UtimacoVersion220 = "{3367270E-43E6-4fed-B57A-0711FAE20CCA}"
*
* [p6pkcs11-slot-5]
* slotType="UtimacoVersion220"
* slotFlags=5
* vendorSlotId=0
* vendorVerifyPIN=true
* vendorPreInitToken=true
* vendorCompat=1
*

Any slot number will work so the section header of "[p6pkcs11-slot-5]" above is arbitrary. The value under the "[p6pkcs11-tokens]" section above defines the GUID of the P6R plugin DLL (.so file for Linux) for Utimaco HSMs.

The second step is to copy the Utimaco provided files: cs_pkcs11_R2.dll (on Windows), cs_pkcs11_R2.so (on Linux), and cs_pkcs11_R2.cfg into the P6R "components" directory so that they can be found and loaded. Then modify the Utimaco configuration file "cs_pkcs11_R2.cfg" based on Utimaco documentation for use of their PKCS#11 API library depending on the Utimaco hardware present. One such document is the Utimaco CryptoServer PKCS11#11 R2 Developer Guide, Document Number 2012-0007, Date May 2014.

SafeNet Luna HSM Integration

A SafeNet Luna HSM can be configured to look like another token. Actually we map one slot of the SafeNet Luna HSM into one slot of our P6R PKCS#11 library. In the example below, P6R slot number 6 is mapped to SafeNet Luna slot number 0 (see the vendorSlotId parameter).

This is easily done by the following two steps. First, define the SafeNet slot in the p6pkcs11.conf file. An example of how to do this is appears below:

* [p6pkcs11-tokens]
* SafeNetLuna = "{AB0258D5-7CC1-422a-916F-9D57F7E70808}"
*
* [p6pkcs11-slot-6]
* slotType="SafeNetLuna"
* slotFlags=5
* vendorSlotId=0
* vendorVerifyPIN=true
* vendorPreInitToken=true
* vendorCompat=3
*

Any slot number will work so the section header of "[p6pkcs11-slot-6]" above is arbitrary. The value under the "[p6pkcs11-tokens]" section above defines the GUID of the P6R plugin DLL (.so file for Linux) for SafeNet Luna HSMs.

The second step is modify the file "p6safenet.conf" by setting the full path to the directory of where the SafeNet Luna PKCS#11 library is installed. For example on Windows:

* [PKCS11]
* libraryPath="C:\Program Files\SafeNet\LunaClient"
*

This allows the P6R code to find and dynamically load the SafeNet PKCS#11 library file (cryptoki.dll for Windows and libCryptoki2.so for Unix). Initializing and configuring the SafeNet Luna HSM requires the use of SafeNet tools that come with the Luna HSM client.

Thales HSM Integration

A Thales nShield Connect HSM can be configured to look like another token. Actually we map one slot of the Thales HSM into one slot of our P6R PKCS#11 library. In the example below, P6R slot number 6 is mapped to Thales HSM slot number 492971158 (0x1d622496) (see the vendorSlotId parameter).

This is easily done by the following two steps. First, define the Thales slot in the p6pkcs11.conf file. An example of how to do this is above in the section Basic Configuration Parameters and is repeated below:

* [p6pkcs11-tokens]
* ThalesVersion201 = "{73BED027-BBE5-44dc-ACCE-302647D9E7BD}"
*
* [p6pkcs11-slot-6]
* slotType="ThalesVersion201"
* slotFlags=5
* vendorSlotId=492971158
* vendorVerifyPIN=true
* vendorPreInitToken=true
* vendorCompat=1
*

Any slot number will work so the section header of "[p6pkcs11-slot-6]" above is arbitrary. The value under the "[p6pkcs11-tokens]" section above defines the GUID of the P6R plugin DLL (.so file for Linux) for Thales HSMs.

The second step is to copy the Utimaco provided files: cknfast-64.dll (64 bit) or cknfast-32.dll (32 bit) (on Windows), and libcknfast.so (on Linux) into the P6R "components" directory so that they can be found and loaded. Then set up and configure the Thales nShield Connect HSM as defined in the Thales Quick Start Guide (N-030140X).

Note, when the nShield is in strict FIPS mode a call to C_GenerateKey() needs the attributes CKA_SENSITIVE and CKA_PRIVATE has to be set to CKA_TRUE. In addition, calls to C_CreateObject() where the calling application is trying to place a key onto the HSM will fail since strict FIPS mode does not allow keys of unknown origin from being loaded into the HSM.

Futurex HSM Integration

A Futurex HSM can be configured to look like another token. Actually we map one slot of the Futurex HSM into one slot of our P6R PKCS#11 library. In the example below, P6R slot number 7 is mapped to Futurex HSM slot number 0 (see the vendorSlotId parameter).

This is easily done by the following two steps. First, define the Futurex slot in the p6pkcs11.conf file. An example of how to do this is above in the section Basic Configuration Parameters and is repeated below:

* [p6pkcs11-tokens]
* FuturexVersion22 = "{D6EBC68A-9D3E-4998-B587-C68B6BD3169C}"
*
* [p6pkcs11-slot-7]
* slotType="FuturexVersion22"
* slotFlags=5
* vendorSlotId=0
* vendorVerifyPIN=true
* vendorPreInitToken=true
* vendorCompat=1
*

Any slot number will work so the section header of "[p6pkcs11-slot-7]" above is arbitrary. The value under the "[p6pkcs11-tokens]" section above defines the GUID of the P6R plugin DLL (.so file for Linux) for Futurex HSMs.

The second step is to copy the Futurex provided files: fxpkcs11x64.dll or fxpkcs11x86.dll (on Windows), libfxpkcs11.so (on Linux) into the P6R "components" directory so that they can be found and loaded. Then set up the Futurex directory with the required SSL certificates and PKCS#11 configuration file. On Windows this directory is "C:\Futurex" and it contains fxpkcs11.cfg configuration file which defines the HSM to connect to and the path to find the required SSL certificates.

DocuSign ARX PrivateServer HSM Integration

A DocuSign ARX PrivateServer HSM can be configured to look like another token. Actually we map one slot of the DocuSign HSM into one slot of our P6R PKCS#11 library. In the example below, P6R slot number 8 is mapped to DocuSign HSM slot number 1 (see the vendorSlotId parameter). It appears that valid slot identifiers on this HSM start at one.

This is easily done by the following two steps. First, define the DocuSign slot in the p6pkcs11.conf file. An example of how to do this is above in the section Basic Configuration Parameters and is repeated below:

* [p6pkcs11-tokens]
* DocuSign220 = "{3A55CD57-71DE-495a-A172-43B604C241C0}"
*
* [p6pkcs11-slot-8]
* slotType="DocuSign220"
* slotFlags=5
* vendorSlotId=1
* vendorVerifyPIN=true
* vendorPreInitToken=true
* vendorCompat=1
*

Any slot number will work so the section header of "[p6pkcs11-slot-8]" above is arbitrary. The value under the "[p6pkcs11-tokens]" section above defines the GUID of the P6R plugin DLL (.so file for Linux) for DocuSign HSMs.

The DocuSign PKCS#11 library is installed in a fixed location on Windows in the "C:\Windows\System32" directory. The library files are: sadaptor64.dll for 64 bit code and sadaptor.dll for 32 bit code. DocuSign provides a Windows application (i.e., PrivateServer Management) that supports the configuration of their HSM client libraries and of PKCS#11 slots on the HSM. See the PrivateServer Installation and Operation Guide, Copyright 2011, Pub. No. CSV.INS.V4.8.1211.

For Linux follow the instructions from the PrivateServer Installation and Operation Guide, Chapter 7, Section "PrivateServer Client Installation for Unix/Linux". In doing so first create a "docusign" directory under the P6R installation in its "components" directory. Then copy the DocuSign csv, ckit, modules, and java directories under the "../components/docusign", directory. The DocuSign PKCS#11 library file on linux is: ../csv/libshare/libcs_pkcs.so. This works for both 32 and 64 bit library code. This is where the P6R PKCS#11 library expects to find the DocuSign libraries.

In configuring the DocuSign PKCS#11 library to run on Linux we need modify the "../csv/utils/cs_pkcs.env" file before running it. This file is a script used to set required environment variables. In modifying this file we suggest the use of full path names instead of the relative path names that appear in the file. So for example, if the P6R component directory was installed in the path "/opt/p6r/components" then the fields in the cs_pkcs.env file would be changed as follows:

* setenv CS_PKCS_LOG /var/p6r/logs/cs_pkcs.log
* setenv CS_PKCS_INI /opt/p6r/components/docusign/cvs/utils/cs_pkcs.ini
* setenv CS_PKCS_DEBUG 0
* setenv ARCS_COMM TCP
* setenv LD_LIBRARY_PATH /opt/p6r/components/docusign/cvs/utils:/opt/p6r/components/docusign/cvs/:/opt/p6r/components/docusign/modules/keymng/libshare:
* /opt/p6r/components/docusign/modules/pinstd/libshare:/opt/p6r/components/docusign/modules/emvstd/libshare:/opt/p6r/components/docusign/modules/crt/libshare:
* /opt/p6r/components/docusign/modules/kek_db/libshare:/usr/local/lib:/usr/local/dt/lib:/opt/p6r/components/docusign/ckit/lib:/opt/p6r/components/docusign/cvs/libshare
* setenv PSV_LOADB_PATH /opt/p6r/components/docusign/cvs/utils/loadb.ini
*

Also all paths that appear in the file "../csv/utils/cs_pkcs.ini" should also use full file paths.

Hewlett Packard Enterprise (HPE) Atalla HSM Network Security Processor (NSP) Integration

An HPE's Atalla HSM (http://www8.hp.com/us/en/software-solutions/hardware-security-module-hsm-atalla-nsp/) can be configured to look like another token. We map one P6R's PKCS11 library slot to one NSP HSM. In the case where an NSP is configured with multiple Virtual NSPs then we map one P6R's PKCS11 library slot to one Virtual NSP. In the example below, both P6R slot numbers 2 and 3 are mapped to one physical HPE machine but to two virtual NSPs. In the example, each Virtual NSP is selected by the port (i.e., tokenNSPPort parameter).

This token supports the following PKCS 11 mechanisms: CKM_AES_KEY_GEN, CKM_DES_KEY_GEN, CKM_DES2_KEY_GEN, CKM_DES3_KEY_GEN, CKM_SHA_1_HMAC, CKM_SHA256_HMAC, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS, CKM_RSA_X_509, CKM_DES_CBC, CKM_DES_CBC_PAD, CKM_DES_CFB8, CKM_DES_CFB64, CKM_DES_OFB64, CKM_DES3_CBC (CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP), CKM_AES_CBC, CKM_AES_CBC_PAD, CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512, CKM_MD2, CKM_MD5, and CKM_RIPEMD160. All digest calculations are done in the PKCS 11 client with the use of OpenSSL, but all other calculations are done on the NSP.

This token supports the following PKCS 11 API functions: C_Initialize, C_Finalize, C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, C_GetMechanismInfo, C_InitToken, C_InitPIN, C_SetPIN, C_OpenSession, C_CloseSession, C_CloseAllSessions, C_GetSessionInfo, C_Login, C_Logout, C_CreateObject, C_DestroyObject, C_GetAttributeValue, C_SetAttributeValue, C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal, C_GenerateRandom, C_GenerateKey (not including domain parameters), C_GenerateKeyPair, C_SignInit, C_Sign, C_SignUpdate, C_SignFinal, C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal, C_DigestInit, C_Digest, C_DigestUpdate, C_DigestFinal, C_EncryptInit, C_Encrypt, C_EncryptUpdate, C_EncryptFinal, C_DecryptInit, C_Decrypt, C_DecryptUpdate, C_DecryptFinal, C_WrapKey, and C_UnwrapKey.

This token supports the following PKCS 11 objects: CKO_CERTIFICATE, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_SECRET_KEY, and CKO_DATA.

For this and all 3rd party tokens the PKCS 11 API functions: C_GetInfo, C_GetFunctionList, C_GetSlotList, and C_CloseAllSessions are handled by the PKCS 11 provider module that dynamically loads all tokens).

The HPE Atalla token does not support any of the following attributes to be passed in as part of the pTemplate parameter of the C_FindObjectsInit API call: CKA_VALUE, CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_EC_PARAMS, and CKA_EC_POINT. If any of these attributes are used C_FindObjectsInit will return the CKR_ARGUMENTS_BAD error.

The Atalla NSP HSM's AKB key format attaches how a key can be used to the key material. The NSP key usage is simple compared to what is possible via the PKCS11 API. As such the NSP token limits what a calling application can specify when creating symmetric key objects only to the following sets: { CKA_ENCRYPT, CKA_DECRYPT }, or { CKA_SIGN, CKA_VERIFY }, or { CKA_WRAP, CKA_UNWRAP } are the only combinations of attributes used to define symmetric key usage that can be set to CK_TRUE at the same time. Thus, for example, trying to set a set of { CKA_ENCRYPT, CKA_SIGN } for a symmetric key will result in an error being returned CKR_TEMPLATE_INCONSISTENT because it is not possible to create a symmetric key on the NSP AKB format with that type of key usage.

The following default attribute values are used if the calling application does not define a value:

* CKA_TOKEN - CK_FLASE
* CKA_DERIVE - CK_FALSE (for CKO_SECRET, CKO_PUBLIC, CKO_PRIVATE keys)
* CKA_SENSITIVE - is always CK_TRUE (except for public keys) since all keys are wrapped in the NSP's MKF
* CKA_ALWAYS_SENSITIVE - is always CK_TRUE (except for public keys)
* CKA_CERTIFICATE_CATEGORY - CK_CERTIFICATE_CATEGORY_UNSPECIFIED (for CKO_CERIFICATE objects)
*

Note that in the PKCS #11 standard the function C_InitToken can be called multiple times. On the very first successful call the token is initialized. Then on any subsequent calls the token is supposed to be re-initialized, which includes deleting all contents on a token. In order to prevent accidental deletion of NSP keys stored in a token our implementation of C_InitToken does not clear the token or replace the label. However, additional calls to C_InitToken can be used to load new TLS credentials into the token that might have expired. This does not stop the deletion of individual keys.

The HPE NSP token allows PIN values to contain any valid UTF8 character just as defined by the PKCS#11 standard (Section 5.5, C_InitToken).

* [p6pkcs11-tokens]
* HPE1 = "{fbea740e-0857-4da3-bc76-9a67a9e161f0}"
*
* [p6pkcs11-slot-2]
* # Other virtual NPSs at ports: 7100, 7200, 7300, 7400, 7500, 7600, 7700, 7800, 7900
* slotType="HPE1"
* slotFlags=5
* vendorSlotId=2
* tokenNSPIP=10.110.10.28
* tokenNSPPort=7000
* tokenNSPFlags=1
* tokenNSPCmd="<9A#KEY#>"
* vendorFlags=1
*
* [p6pkcs11-slot-3]
* slotType="HPE1"
* slotFlags=5
* vendorSlotId=3
* tokenNSPIP=10.110.10.28
* tokenNSPPort=7100
* tokenNSPFlags=3
* tokenTLSRootPEM="CACERT_7100.pem"
* tokenConnectTimeout = 5000
* tokenSendTimeout = 5000
* tokenReceiveTimeout = 10000
* vendorFlags=1
* # tokenSoftKeystore = "postgresql8://unittester/unittester/unitsrv1.corp.p6r.com//5432/pkcs11"));
*

The NSP has no notion of PKCS11 slots so we set the "vendorSlotId" parameter to the same slot number as the P6R slot number (e.g., "vendorSlotId=2" is set for "[p6pkcs11-slot-2]" above).

The "tokenNSPIP" configuration parameter (string value) is used to configure the IP address of the NSP hardware.

The "tokenTLSRootPEM" configuration parameter (string value) points to a file that contails the TLS root certificate of the NSP. This allows standard TLS network connection to be made to the NSP (see slot 3 above). This certificate can be replaced by a call to C_InitToken() or by use of the PKCS 11 command line took "-it" (i.e., initialize token) function. This certificate replacement is done on an already initialized token and can be used to replace an expired certificate. The HPE token does NOT delete anything else during a call to C_InitToken(). Note that the replace certificate must have the same subject as the previously configured certificate.

The "tokenNSPFlags" configuration parameter (numeric bit mask) defines token specific configuration options. This parameter is an unsigned integer bit mask of the following flags: { 0x0001 - log NSP messages, 0x0002 - use TLS for network connections, 0x0004 - C_SeedRandom always returns CKR_OK, 0x0008 - use 'p' NSP key usage for RSA key generation [and allows the use of the cipher CKM_RSA_X_509]}. This parameter has a default value of 0x0002 - use TLS.

The "tokenMaxBufSize" configuration parameter (positive numeric value) defaults to "65556" bytes and defines the size of the NSP tokens buffers.

The "tokenConnectTimeout", "tokenSendTimeout", and "tokenReceiveTimeout" configuration parameters (positive numeric values) pass to the NSP token network timeouts in milliseconds for TCP connection, send, and receive operations respectively. These parameters have a default value of 5000 milliseconds.

The "tokenNSPCmd", is an optional configuration parameter (string value) used to send an out-of-band command to the NSP HSM when C_GetTokenInfo() is called, or when the "-lt" list token option is used in the PKCS#11 Command Line Tool. If logging is turned on the user can then see the response from the NSP. This parameter can take any ASCII NSP command sequence upto 3000 characters long.

The "vendorFlags" is an optional configuration parameter (numeric bit mask) and for this token can have the following values: { 0x0001 - recover bad signature (when the signature on the NSP token's keystore fails allow us to open it anyway) }

The "tokenSoftKeystore" configuration parameter (string value), is optional and can either the full path to a directory where the slot's keystore is to be created or a database URI of the standard for: "postgresql8://...". When this parameter is not provided then a default location is used. Otherwise, When using the full path to a local directory then a Sqlite database will be used. This keystore holds all the PKCS 11 defined objects for this token (e.g., CKO_SECRET_KEY, CKO_PUBLIC_KEY, CKO_PRIVATE_KEY, CKO_CERIFICATE).

NSP Command and Response Logging

Sometimes it is necessary to see both the NSP command from the PKCS#11 library and the NSP response form the Atalla HSM to diagnose a problem. To do this the following configuration is required: {1) tokenNSPFlags has to have the 0x0001 bit in that bit mask on, and (2) the file p6pkcs11.en_us requires the following modification.

* [hpe.com.pkcs11]
* libraryTrace = "info",2,"HPE NSP token, %1$ (error: %2$, %6$) (extra1: %3$ %4$) (extra2: %5$)"
* nspIncompleteMsg = "info",2,"HPE NSP token [%1$:%2$], incomplete response [%3$] length: %4$"
* nspCommand = "info",2,"HPE NSP token [%1$:%2$], command [%3$] sent: %4$"
* nspResponse = "info",2,"HPE NSP token [%1$:%2$], response [%3$] received: %4$"
* tokenTrace = "info",2,"HPE NSP token, %1$ (error: %2$, %6$) (extra1: %3$ %4$) (extra2: %5$)"
*

Change in the above section the '2' to '0' which is the log level. Once the value is '0' then these log statements will appear in the logs showing all the NSP commands and their matching PKCS#11 calls.

AES ENCRYPTION ON HPE TOKEN

On older HPE Atalla HSMs, in order to perform AES encryption on the HPE Atalla HSM the AES key has to be created using the SCA device. Then that AES key, in AKB format encrypted under the NSP's MFK can be loaded directly into the P6R token via the following PKCS#11 code. (Note, newer model HSMs allow AES key generation via the PKCS#11 API.)

* // -> load the AES key into the token
* CK_ATTRIBUTE keyTemplate[15];
* CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
* CK_KEY_TYPE keyType = CKK_HPE_AES_NSPWRAPPED;
* CK_UTF8CHAR label[] = "AESkey1";
* CK_BBOOL bTFlag = CK_TRUE;
* CK_ULONG keyLength = 32; // -> key length in bytes
* CK_RV rv = CKR_OK;
*
* // -> 256 bit NSP key generated under our MFK
* static P6CHAR* pKeyMaterial = (P6CHAR*)"1DJNE000,10C229E920E1B4FDD967E4EBB1B03F919EFE7FC70ED398527F1BCC27F75811AC,4851CE59462C88A4";
*
* --- assume PKCS#11 code that calls C_OpenSession( hSession ) and C_Login()... ---
*
* keyTemplate[0].type = CKA_CLASS;
* keyTemplate[0].pValue = &objClass;
* keyTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
* keyTemplate[1].type = CKA_KEY_TYPE;
* keyTemplate[1].pValue = &keyType;
* keyTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
* keyTemplate[2].type = CKA_TOKEN;
* keyTemplate[2].pValue = &bTFlag;
* keyTemplate[2].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[3].type = CKA_LABEL;
* keyTemplate[3].pValue = label;
* keyTemplate[3].ulValueLen = 7;
* keyTemplate[4].type = CKA_VALUE_LEN;
* keyTemplate[4].pValue = &keyLength;
* keyTemplate[4].ulValueLen = sizeof(CK_ULONG);
* keyTemplate[5].type = CKA_ENCRYPT;
* keyTemplate[5].pValue = &bTFlag;
* keyTemplate[5].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[6].type = CKA_DECRYPT;
* keyTemplate[6].pValue = &bTFlag;
* keyTemplate[6].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[7].type = CKA_VALUE;
* keyTemplate[7].pValue = pKeyMaterial;
* keyTemplate[7].ulValueLen = 90;
* rv = C_CreateObject( hSession, (CK_ATTRIBUTE_PTR)keyTemplate,8, &hKey );
*

First, notice the use of a vendor defined CK_KEY_TYPE 'CKK_HPE_AES_NSPWRAPPED'. This value is defined in the file pkcsllp6r.h. It is this value that informs the HPE token how to handle the contents of the CKA_VALUE attribute. Second, the actual NSP key referred to by the pKeyMaterial variable in the above example can be read in from a file. Third, an AES key can also be imported into the HPE token by use of P6R's PKCS11 Command Line Tool from a file. Once the key is loaded into the HPE token it can be used just like any key that was created via a C_GenerateKey() and C_GenerateKeyPair() call.

The above scheme can also be used to load in DES and RSA NSP keys with the use of the following vendor defined key types (see file pkcs11p6r.h): CKK_HPE_DES_NSPWRAPPED. CKK_HPE_DES2_NSPWRAPPED, CKK_HPE_DES3_NSPWRAPPED, CKK_HPE_RSAPUB_NSPWRAPPED, and CKK_HPE_RSAPRV_NSPWRAPPED.

KEY EXPORT IN NON-AKB FORMAT ON HPE TOKEN

If a user wishes to export a key currently stored in the HPE token into a non-AKB format the following steps need to take place. First, the user needs to generate a KEK using the SCA device. This KEK is then loaded into the HPE token either using the approach described above or via the PKCS11 Command Line Tool. Note, that such a key MUST have the CK_WRAP PKCS#11 attribute set. Here is the PKCS#11 code to do export a key:

* CK_ATTRIBUTE keyTemplate[15];
* CK_BYTE exportBuf[600];
* CK_ULONG exportLength = 600;
* CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
* CK_KEY_TYPE keyType = CKK_HPE_DES3_NSPWRAPPED;
* CK_UTF8CHAR label[] = "ExportKEK1";
* CK_BBOOL bTFlag = CK_TRUE;
* CK_ULONG keyLength = 24;
* CK_RV rv = CKR_OK;
* CK_MECHANISM wrapMech = { CKM_DES3_CBC, NULL_PTR, 0 };
*
* // Here are new AKB-KEKs based on this triple length KEK: 0123456789ABCDEF FEDCBA9876543210 5454676776768989, check digits B51E
* //
* // -> KEK for exporting keys, for C_Wrap()
* static P6CHAR* pExportKEK = (P6CHAR*)"1KDNE000,7BC98D21224A2C8579928F06D498C48F2250CA1DBF3C8316,8224EDAC00A8E8C3";
*
* --- assume PKCS#11 code that calls C_OpenSession( hSession ) and C_Login()... ---
*
* // -> first load the KEK into the HPE token
* keyTemplate[0].type = CKA_CLASS;
* keyTemplate[0].pValue = &objClass;
* keyTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
* keyTemplate[1].type = CKA_KEY_TYPE;
* keyTemplate[1].pValue = &keyType;
* keyTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
* keyTemplate[2].type = CKA_TOKEN;
* keyTemplate[2].pValue = &bTFlag;
* keyTemplate[2].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[3].type = CKA_LABEL;
* keyTemplate[3].pValue = label;
* keyTemplate[3].ulValueLen = 10;
* keyTemplate[4].type = CKA_VALUE_LEN;
* keyTemplate[4].pValue = &keyLength;
* keyTemplate[4].ulValueLen = sizeof(CK_ULONG);
* keyTemplate[5].type = CKA_WRAP; // -> HAS TO BE SET
* keyTemplate[5].pValue = &bTFlag;
* keyTemplate[5].ulValueLen = sizeof(CK_BBOOL);
* keyTemplate[6].type = CKA_VALUE;
* keyTemplate[6].pValue = pExportKEK;
* keyTemplate[6].ulValueLen = 74;
* rv = C_CreateObject( hSession, (CK_ATTRIBUTE_PTR)keyTemplate, 7, &hExportKEK );
*
* --- assume PKCS#11 code puts a valid handle into hDataKey to export, could be using C_FindObjects() ... ---
*
* // -> export the data key by wrapping it in the Export KEK without the AKB format
* rv = C_WrapKey( hSession, &wrapMech, hExportKEK, hDataKey, (CK_BYTE_PTR)exportBuf, &exportLength );
*
*

At the end of the above example the buffer 'exportBuf' contents the data key wrapped using the key referenced by 'pExportKEK'. Note that the original data key, referenced to by the handle 'hDataKey', still exists in the HPE token (i.e., the C_Wrap() key function does not remove the key).

KEY IMPORT FROM NON-AKB FORMAT ON HPE TOKEN

If a user wishes to import a key that has previously been exported using the C_Wrap() call of the HPE token, or from an Atalla NSP directly via Command 1A, the following steps are required. First, the user needs to generate the proper import KEK using the SCA device for the NSP importing the key. This means, of course, that the same "in-the-clear" key material used for the export KEK (see above example) has to be re-used. What is different for importing is that the key usage of the final import key has to be taken into account in order to generate the proper AKB format. So if the final imported key is to be used for encrypt / decrypt operations then it must use a KEK for data keys, whereas if the imported key is to be used for HMAC operations then a different KEK is to be generated (refer to NSP documentation).

In the example below, we show several different KEK keys for importing wrapped keys. Second, once generated these import KEK keys must be loaded into the HPE token (see example above).

* CK_ATTRIBUTE importTemplate[15];
* CK_BYTE importBuf[600];
* CK_ULONG importLength = 600;
* CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
* CK_KEY_TYPE keyType = CKK_DES3;
* CK_UTF8CHAR label[] = "ImportedDESKey";
* CK_BBOOL bTFlag = CK_TRUE;
* CK_ULONG keyLength = 24;
* CK_RV rv = CKR_OK;
* CK_MECHANISM wrapMech = { CKM_DES3_CBC, NULL_PTR, 0 };
*
* // Here are AKB-KEKs based on this triple length KEK: 0123456789ABCDEF FEDCBA9876543210 5454676776768989, check digits B51E
* //
* // -> KEK for exporting keys, for C_Wrap()
* static P6CHAR* pExportKEK = (P6CHAR*)"1KDNE000,7BC98D21224A2C8579928F06D498C48F2250CA1DBF3C8316,8224EDAC00A8E8C3";
*
* // -> KEK for importing data keys, for C_Unwrap()
* static P6CHAR* pDataKEK = (P6CHAR*)"1DDNE0I0,83A485EE47EB6E2B2BF59D9E760443CC513313F97AEE93B6,E0C8DEFF7A2E999E";
*
* // -> KEK for importing HMAC-SHA1 keys, for C_Unwrap()
* static P6CHAR* pHMAC1KEK = (P6CHAR*)"1MHNE0I0,E09377F1DF056250E480D3C2264217C9C15AA5AD7C889A08,36C56D78866C0F08";
*
* // -> KEK for importing MAC keys (commands 98, 99), for C_Unwrap()
* // static P6CHAR* pMACKEK = (P6CHAR*)"1M2NE0I0,620A298F878FEE056FF0E6842CF83C3008485F1718E7DDB6,5D91A0D98D2A855F";
*
* --- assume PKCS#11 code that calls C_OpenSession( hSession ) and C_Login()... ---
*
* --- add PKCS#11 code to load the pDataKEK into the token (see previous example), sets the value in hImportDataKEK ... ---
*
* --- assume code that gets the wrapped key to import to be placed into the importBuf array ... ---
*
* // -> import back in the DES3 key we exported in the last example
* importTemplate[0].type = CKA_CLASS;
* importTemplate[0].pValue = &objClass;
* importTemplate[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
* importTemplate[1].type = CKA_KEY_TYPE;
* importTemplate[1].pValue = &keyType;
* importTemplate[1].ulValueLen = sizeof(CK_KEY_TYPE);
* importTemplate[2].type = CKA_TOKEN;
* importTemplate[2].pValue = &bTFlag;
* importTemplate[2].ulValueLen = sizeof(CK_BBOOL);
* importTemplate[3].type = CKA_LABEL;
* importTemplate[3].pValue = label;
* importTemplate[3].ulValueLen = 14;
* importTemplate[4].type = CKA_VALUE_LEN;
* importTemplate[4].pValue = &keyLength;
* importTemplate[4].ulValueLen = sizeof(CK_ULONG);
* importTemplate[5].type = CKA_ENCRYPT;
* importTemplate[5].pValue = &bTFlag;
* importTemplate[5].ulValueLen = sizeof(CK_BBOOL);
* importTemplate[6].type = CKA_DECRYPT;
* importTemplate[6].pValue = &bTFlag;
* importTemplate[6].ulValueLen = sizeof(CK_BBOOL);
* rv = C_UnwrapKey( hSession, &wrapMech, hImportDataKEK, importBuf, importLength, (CK_ATTRIBUTE_PTR)importTemplate, 7, &hDataKey );
*
*

At the end of the above example the wrapped key that was in importBuf has been decrypted using the value represented by the 'pDataKEK' and re-encrypted using the NSP's MFK. The newly imported key is in AKB format and is loaded into the HPE token with the hDataKey handle pointing to it. In the above example, we imported the key with the key useage for encrypt / decrypt operations and so we also needed to set the PKCS#11 CKA_ENCRYPT and CKA_DECRYPT attributes (see above).