PKCS#11
The PKCS#11 interface is the core of the PKI client. All other components calls this component using the documented interface to guarantee that all functionality is available for your application. For example, there is no other undocumented way that is used internally to access the smart card.
Documented does not mean that all functionality is available using standard PKCS#11 functions. There is some functionality that will need our extensions to the standard, see below. |
The basic understanding of PKCS#11 is not a part of this documententation. Instead you will need to read the official standard.
In order to make the reading of this document easier:
- Token
-
A device that stores private keys and certificates, such as a smart card.
- Slot
-
Something that stores a token, for example a smart card reader.
The PKCS#11 standard has two major limitations:
-
It does not support multiple PINs for the same token
-
It does not support any unlocking of PIN, for example by using PUK.
Multiple PINs
The lack of support for multiple PINs is really a major drawback. Fortunately there was a good workaround introduced in version 2.11 of the standard. Instead of considering one smart card as a token, each token is mapped to several virtual tokens, and one for each PIN. This workaround works well since it allows applications that are not aware of multiple PINs to support it without any modifications.
The slot description for each virtual token will have the same string to allow applications that are aware of multiple PINs to modify the visual appearance accordingly:
Workaround
-
Slot 1: "Smart Card Reader One"
-
Token 1: "Smart Card (PIN1)"
-
Slot 2: "Smart Card Reader One"
-
Token 2: "Smart Card (PIN2)"
The format of the token label is:
<token name> (<pin name>)"
An application unaware of the multiple PINs concept treats the virtual token in the same way as multiple slots (smart card readers).
Multiple PINs in application
As mentioned above in Multiple PINs, the application should be tricked into support multiple PINs. But there is a design flaw in some applications that need to be addressed. There are applications that never have realized that there may be multiple slots:
A certificate and corresponding public key are both public objects that may be read without logon towards token. A private key can require logon towards token, but may still in some cases be used without logon. For example when using single sign-on.
Never ever log on to all available tokens before searching for public objects, such as certificates. |
The recommended behavior for an application using certificates and private keys:
-
Read all certificates for all slots.
-
Read public key corresponding to the certificate (match with CKA_ID).
The second step guarantees that there will be a private key, since some tokens will store extra certificates without the private key, such as CA-certificates.
The first step also guarantees that multiple certificates for the same private keys are handled without any problem. Multiple certificates for the same private key may initially seem strange, but is common when a token has limited space for additional private keys. And it is even more important when an additional certificate is issued based on the first certificate.
The application should continue to use the certificate internally until the private key is necessary:
-
When the private key is necessary, search for it (match with CKA_ID).
-
If the private key is found, skip logon.
-
If the private key is not found, present a dialog with applicable information from the certificate/token/slot, and then log on and search again.
Library version
Variable CK_INFO::libraryVersion
will tell 2.11, since later versions have removed the appendix with multiple PINs support.
The suggestions for handling of multiple PINs in later versions of the standard is basically useless, since they require application awareness.
Size of CK_ULONG
The definition of CK_ULONG in the standard tells "at least 32-bits value." A good guess would be that computers using 32-bit architectures use 32-bits CK_ULONG, and 64-bit architectures use 64-bits CK_ULONG. Unfortunately this is not true, since RSA Labs provided a default header file that Microsoft Developer Studio compiler translated to 32-bits even for 64-bits architectures. All other compilers followed the architecture size:
-
Windows 32-bits ⇒ CK_ULONG 32-bits
-
Windows 64-bits ⇒ CK_ULONG 32-bits
-
Non-Windows-OS 32-bits ⇒ CK_ULONG 32-bits
-
Non-Windows-OS 64-bits ⇒ CK_ULONG 64-bits
The size of CK_ULONG is vital when doing interoperability test, so this information will be available in trace:
PKCS11 - Little endian build (32-bits CK_ULONG)
Currently all supported architectures are little endian, but there are still support for custom big-endian builds, so this information is also sent to trace.
Nothing will work if application and library have different definitions of CK_ULONG, and the result will most likely be a crash if there is a mismatch. |
The initial test with a new application is to verify that our library and the calling application is using the same size for CK_ULONG. Our library may be built with a different size. Contact support for more information.
PIN unlocking
PIN unlocking is not supported at all in the standard, and some new functions are added, since this require new types of operation.
CK_RV CK_CALL_SPEC
C_UnlockPIN(
CK_ULONG session,
CK_CHAR* puk,
CK_ULONG pukLen,
CK_CHAR* pin,
CK_ULONG pinLen)
CK_RV
C_SetTokenTimeout(
CK_ULONG slotID,
CK_ULONG timeout)
CK_RV
C_GenerateChallenge(
CK_ULONG session,
CK_BYTE* challengeData,
CK_ULONG* challengeDataLen)
CK_RV CK_CALL_SPEC
C_UnlockPIN(
CK_ULONG session,
CK_CHAR* response,
CK_ULONG responseLen,
CK_CHAR* pin,
CK_ULONG pinLen)
Initialize/Reset token
The necessary information for C_InitToken and C_ResetToken is token dependent, and is given using C_SetVariable.
Initialize token — C_InitToken
The function C_InitToken initializes the token, but the C_InitToken function does not provide all information necessary to initialize.
The C_InitToken function also requires CKU_SO
access.
Reset token — C_ResetToken
In some situations the normal CKU_USER
should be able to reset the token.
Thus, another function is added, C_ResetToken.
CK_RV CK_CALL_SPEC
C_InitToken(
CK_SLOT_ID slotID,
CK_CHAR* soPin,
CK_ULONG soPinLen,
CK_CHAR* label)
CK_RV CK_CALL_SPEC
C_ResetToken(
CK_SLOT_ID slotID,
CK_CHAR* pin,
CK_ULONG pinLen)
CK_RV CK_CALL_SPEC
C_SetVariable(
const char* name,
const char* value)
Reinitialization of specific tokens — C_Reinitialize
Management of tokens sometimes requires reinitialization of specific tokens. Thus, the C_Reinitialize function is added to provide this:
CK_RV
C_Reinitialize(
CK_SLOT_ID slotID)
The C_Reinitialize function should be used with care, since it closes all existing sessions towards the token. It can also clear logon status, depending on single sign-on configuration.
Read information
Some information is always available without initialization, C_Initialize, and is accessed using C_GetVariable.
The current variables are netid-system-info
and netid-soft-token-type
.
CK_RV CK_CALL_SPEC
C_GetVariable(
const char* name,
char* value,
CK_ULONG valueLen)
Token event
The PKCS#11 component provides the C_WaitForSlotEvent function for token events. The C_WaitForSlotEvent function is limited for those applications running with multiple threads that need to detect token events. The reason for this is that the first thread accessing gets the event, and the next thread will not detect anything. Thus, the C_HasNewEvent function is added:
CK_RV CK_CALL_SPEC
C_HasNewEvent(
CK_ULONG* lastEvent)
External components
The PKCS#11 component is the core of Net iD Client. But sometimes external functionality is added, such as mobile platforms.
CK_RV CK_CALL_SPEC
C_AddExternalSlot(
CK_ADD_SLOT* addSlot,
CK_ULONG* slotID,
CK_ULONG* count)
CK_RV CK_CALL_SPEC
C_RemoveExternalSlot(
CK_ULONG slotID)
C_AddExternalGenerator(
CK_MECHANISM_TYPE type,
const char* name,
CK_GENERATOR_CALLBACK callback)
CK_RV CK_CALL_SPEC
C_SetTraceCallback(
CK_TRACE_CALLBACK callback)
Special data object
Special data objects are available to allow other components to access information that are limited or missing by the PKCS#11 standard.
Token serial number
The CK_TOKEN_INFO::serialNumber
is limited to 16 bytes, and sometimes more characters are needed.
The CK_TOKEN_INFO::serialNumber
contains a stripped version of the serial number, but the full serial number is available using this object:
[00] Label: 'TokenSerialNumber'
Application: 'PKCS #15'
Private: false
Modifiable: true
Value: '9752269885705648365'
ATR
The ATR object will exist for all smart card tokens and tell the current ATR.
[01] Label: 'ATR'
Application: 'NIST SP 800-73 [PIV]'
Private: false
Modifiable: false
Value: 3BF81300008131FE15597562696B657934D4
Token label
The CK_TOKEN_INFO::label
is limited to 32 bytes, and sometimes more characters are needed.
The CK_TOKEN_INFO::label
contains a stripped version of the label, but the full label is available using this object:
[02] Label: 'TokenLabel'
Application: 'Net iD'
Private: false
Modifiable: true
Value: 'Telia EID IP5a (legitimering)'
Update counter
No standard methods are available to detect that the token is updated Usually this is not a problem, but there are situations when this is important. Thus, another object is added to give this information. The value is dependent on token, but one should consider the token as updated as soon as the value is different.
[03] Label: 'UpdateCount'
Application: 'Net iD'
Private: false
Modifiable: true
Value: 02045D5D444E02045D6CBCE9
Algorithms
The supported algorithms:
-
RSA-1024/RSA-1536/RSA-2048/RSA-3072/RSA-4096
-
ECC-256/ECC-384/ECC-521
-
DES/3DES
-
AES-128/AES-192/AES-256
-
MD5/SHA-1/SHA-224/SHA-256/SHA-384/SHA-512
The supported RSA padding algorithms:
-
RSA standard
-
RSA OAEP
-
RSA PSS
The algorithms above are those supported by our client, but the supported list will be limited by the used token. For example, some tokens require to understand what is signed or encrypted but do not support OAEP/PSS. The most common limitation is AES key wrapping, since it requires OAEP padding. And this will usually not work when used with old smart cards. A funny thing is that it will work with even older smart cards, since those smart cards allow RSA raw.
Algorithm support is limited by the token used, such as old smart cards |
The important rule is that you must verify your smart card before you can say anything about the algorithms supported. This is because the limitation can be set during smart card personalization For example a private key must understand the data-to-be-signed. A smart card specification tells what is possible to do with a smart card. And a smart card profile tells what is possible with a specific personalized smart card.
Require a smart card profile document from your smart card vendor. |