PKCS#11
Page updated: 2023-07-07
What it is
PKCS#11 is a cryptographic token interface standard, which specifies an API, called Cryptoki.
PKCS#11 was developed by the RSA Labs but is now an open standard managed by the OASIS PKCS 11 Technical Committee.
https://www.oasis-open.org/committees/pkcs11/
If you want to have support for multiple platforms, and you know what you do, PKCS#11 can be a good choice for buildning an application using certificates.
Version
The current version of the standard is 2.40, but our implementation will return 2.11 as version information.
The differences between the two versions are:
a) Algorithm extensions not concerning smart cards
b) Changed suggestion for handling multiple PINs. The suggestion regarding multiple PINs is useless and will be removed in future versions of the standard.
The implementation in Net iD Enterprise and Net iD Client is very stable and we seldom need to change anything. The last change was the addition of PKCS#11 key attribute CKA_ALWAYS_AUTHENTICATE in 6.8.4.10.
Applications implementing the standard should only be concerned with the major version (2) and minor versions adding support for specific algorithms which are needed, i.e. in those rare cases where a new specific algorithm is mandatory.
Third-party Package
The PKCS#11 library may be installed in any location; it has no other binary dependencies, and only needs the configuration file for license information.
For library version 5.4 and later the configuration file may be included in the binary, there is no need for a separate file.
Example
The example will test three standard operations with a smart card: create/verify a digital signature, encrypt/decrypt a message and wrap/unwrap a secret key. The example uses Microsoft Developer Studio, but is written in standard C and should be possible to compile using any compiler. Download sample code:
Link your application to Pointsharps PKCS#11 implementation
Net iD Enterprise
Windows => iidp11.dll
Linux => libiidp11.so
macOS => libiidp11.dylib
Net iD Client
Windows => netid.dll
Linux => libnetid.so
macOS => /usr/local/lib/netid/libnetid.dylib
a) You should list all available slots (C_GetSlotList)
b) Then open a session for every found slot and search for all certificates in all slots.
c) When all certificates have been collected check them against the rules set up by your application and the context.
d) If you get more than one hit you should present a decent dialog where the user can select a certificate.
e) Then proceed with the desired operations.
Details can be found here: https://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html
Cryptoki specifications
Version | major | minor |
---|---|---|
1.0 | 0x01 | 0x00 |
2.01 | 0x02 | 0x01 |
2.10 | 0x02 | 0x0a |
2.11 | 0x02 | 0x0b |
2.20 | 0x02 | 0x14 |
2.30 | 0x02 | 0x1e |
2.40 | 0x02 | 0x28 |
Prefixes
Prefix | Description |
---|---|
C_ | Function |
CK_ | Data type or general constant |
CKA_ | Attribute |
CKC_ | Certificate type |
CKD_ | Key derivation function |
CKF_ | Bit flag |
CKG_ | Mask generation function |
CKH_ | Hardware feature type |
CKK_ | Key type |
CKM_ | Mechanism type |
CKN_ | Notification |
CKO_ | Object class |
CKP_ | Pseudo-random function |
CKS_ | Session state |
CKR_ | Return value |
CKU_ | User type |
CKZ_ | Salt/Encoding parameter source |
h | a handle |
ul | a CK_ULONG |
p | a pointer |
pb | a pointer to a CK_BYTE |
ph | a pointer to a handle |
pul | a pointer to a CK_ULONG |
PKCS#11 Error Codes
Name | HEX | DEC |
---|---|---|
CKR_OK | 0x00000000 | |
CKR_CANCEL | 0x00000001 | |
CKR_HOST_MEMORY | 0x00000002 | |
CKR_SLOT_ID_INVALID | 0x00000003 | |
CKR_GENERAL_ERROR | 0x00000005 | |
CKR_FUNCTION_FAILED | 0x00000006 | |
CKR_ARGUMENTS_BAD | 0x00000007 | |
CKR_NO_EVENT | 0x00000008 | |
CKR_NEED_TO_CREATE_THREADS | 0x00000009 | |
CKR_CANT_LOCK | 0x0000000A | |
CKR_ATTRIBUTE_READ_ONLY | 0x00000010 | |
CKR_ATTRIBUTE_SENSITIVE | 0x00000011 | |
CKR_ATTRIBUTE_TYPE_INVALID | 0x00000012 | |
CKR_ATTRIBUTE_VALUE_INVALID | 0x00000013 | |
CKR_DATA_INVALID | 0x00000020 | |
CKR_DATA_LEN_RANGE | 0x00000021 | |
CKR_DEVICE_ERROR | 0x00000030 | 48 |
CKR_DEVICE_MEMORY | 0x00000031 | 49 |
CKR_DEVICE_REMOVED | 0x00000032 | |
CKR_ENCRYPTED_DATA_INVALID | 0x00000040 | |
CKR_ENCRYPTED_DATA_LEN_RANGE | 0x00000041 | |
CKR_FUNCTION_CANCELED | 0x00000050 | |
CKR_FUNCTION_NOT_PARALLEL | 0x00000051 | |
CKR_FUNCTION_NOT_SUPPORTED | 0x00000054 | |
CKR_KEY_HANDLE_INVALID | 0x00000060 | |
CKR_KEY_SIZE_RANGE | 0x00000062 | |
CKR_KEY_TYPE_INCONSISTENT | 0x00000063 | |
CKR_KEY_NOT_NEEDED | 0x00000064 | |
CKR_KEY_CHANGED | 0x00000065 | |
CKR_KEY_NEEDED | 0x00000066 | |
CKR_KEY_INDIGESTIBLE | 0x00000067 | |
CKR_KEY_FUNCTION_NOT_PERMITTED | 0x00000068 | |
CKR_KEY_NOT_WRAPPABLE | 0x00000069 | |
CKR_KEY_UNEXTRACTABLE | 0x0000006A | |
CKR_MECHANISM_INVALID | 0x00000070 | |
CKR_MECHANISM_PARAM_INVALID | 0x00000071 | |
CKR_OBJECT_HANDLE_INVALID | 0x00000082 | |
CKR_OPERATION_ACTIVE | 0x00000090 | 144 |
CKR_OPERATION_NOT_INITIALIZED | 0x00000091 | |
CKR_PIN_INCORRECT | 0x000000A0 | 160 |
CKR_PIN_INVALID | 0x000000A1 | 161 |
CKR_PIN_LEN_RANGE | 0x000000A2 | |
CKR_PIN_EXPIRED | 0x000000A3 | |
CKR_PIN_LOCKED | 0x000000A4 | 164 |
CKR_SESSION_CLOSED | 0x000000B0 | |
CKR_SESSION_COUNT | 0x000000B1 | |
CKR_SESSION_HANDLE_INVALID | 0x000000B3 | |
CKR_SESSION_PARALLEL_NOT_SUPPORTED | 0x000000B4 | |
CKR_SESSION_READ_ONLY | 0x000000B5 | |
CKR_SESSION_EXISTS | 0x000000B6 | |
CKR_SESSION_READ_ONLY_EXISTS | 0x000000B7 | |
CKR_SESSION_READ_WRITE_SO_EXISTS | 0x000000B8 | |
CKR_SIGNATURE_INVALID | 0x000000C0 | |
CKR_SIGNATURE_LEN_RANGE | 0x000000C1 | |
CKR_TEMPLATE_INCOMPLETE | 0x000000D0 | |
CKR_TEMPLATE_INCONSISTENT | 0x000000D1 | |
CKR_TOKEN_NOT_PRESENT | 0x000000E0 | 224 |
CKR_TOKEN_NOT_RECOGNIZED | 0x000000E1 | |
CKR_TOKEN_WRITE_PROTECTED | 0x000000E2 | |
CKR_UNWRAPPING_KEY_HANDLE_INVALID | 0x000000F0 | |
CKR_UNWRAPPING_KEY_SIZE_RANGE | 0x000000F1 | |
CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT | 0x000000F2 | |
CKR_USER_ALREADY_LOGGED_IN | 0x00000100 | 256 |
CKR_USER_NOT_LOGGED_IN | 0x00000101 | 257 |
CKR_USER_PIN_NOT_INITIALIZED | 0x00000102 | |
CKR_USER_TYPE_INVALID | 0x00000103 | |
CKR_USER_ANOTHER_ALREADY_LOGGED_IN | 0x00000104 | |
CKR_USER_TOO_MANY_TYPES | 0x00000105 | |
CKR_WRAPPED_KEY_INVALID | 0x00000110 | |
CKR_WRAPPED_KEY_LEN_RANGE | 0x00000112 | |
CKR_WRAPPING_KEY_HANDLE_INVALID | 0x00000113 | |
CKR_WRAPPING_KEY_SIZE_RANGE | 0x00000114 | |
CKR_WRAPPING_KEY_TYPE_INCONSISTENT | 0x00000115 | |
CKR_RANDOM_SEED_NOT_SUPPORTED | 0x00000120 | |
CKR_RANDOM_NO_RNG | 0x00000121 | |
CKR_DOMAIN_PARAMS_INVALID | 0x00000130 | |
CKR_BUFFER_TOO_SMALL | 0x00000150 | 336 |
CKR_SAVED_STATE_INVALID | 0x00000160 | |
CKR_INFORMATION_SENSITIVE | 0x00000170 | |
CKR_STATE_UNSAVEABLE | 0x00000180 | |
CKR_CRYPTOKI_NOT_INITIALIZED | 0x00000190 | |
CKR_CRYPTOKI_ALREADY_INITIALIZED | 0x00000191 | |
CKR_MUTEX_BAD | 0x000001A0 | |
CKR_MUTEX_NOT_LOCKED | 0x000001A1 | |
CKR_VENDOR_DEFINED | 0x80000000 |
Defined mechanism types for Cryptoki
Not yet in place. See the standard itself.
Sample 1 - How PKCS#11 can look like
An application using PKCS#11 to list slots and their eventual content
Sample 2 - An application talks PKCS#11
Another application using PKCS#11 to list slots and their eventual content