PKCS#11 – Implementation Details

Slots and Tokens

A PKCS#11 token represents a combination of persistent object storage, and access to cryptographic hardware. In releases prior to 6.0.5.0, the NVIDIA PKCS#11 implementation supported a single token instance– a single persistent storage area (ID 2) and a single set of hardware (CCPLEX). In 6.0.5.0 and future releases, multiple tokens are supported.

Three types of hardware are supported; these need to be represented in different PKCS#11 tokens, as they represent different hardware:
  • CCPLEX (the largest set of cryptographic hardware support).
  • TSEC (supports AES CMAC sign and verify exclusively).
  • FSI (key management only, no crypto operations supported).

There is a requirement for object access control for CCPLEX. This is to allow different applications to use the same CCPLEX hardware, but with access to different sets of objects. For example, you can have an application that processes sensor data with one set of keys and a webstore application with a different set of keys. Each application must not be able to access the other set of objects but must execute operations on the same set of cryptographic hardware. This is implemented by having multiple PKCS#11 tokens for CCPLEX hardware, each with their own storage areas and access protection GIDs.

There is a requirement to protect safety applications from changes to token objects while they are running (UNECE 156a 7.2.2.1.3). There may also be other, non-safety critical applications that need the ability to change token objects at runtime. To allow for this, each configuration of hardware and access control will have a dynamic token view and a safety token view. The dynamic token allows for token objects to be added, updated, and deleted, and once added can be used immediately. The safety token has a static view of the content of the persistent storage as it was at boot time - objects can be accessed, but not altered, added, or deleted in this view.

To alter the objects in the safety view:

  • Make the changes in the dynamic view of the same storage ID
  • Call C_NVIDIA_CommitTokenObjects() with no PKCS#11 sessions open on any safety token (this is to prevent safety-critical operations stalling as the commit happens)
  • Either reboot, or go through an SC7 cycle (calling C_Finalize() before suspending and C_Initialize() after resuming)

Twenty seven tokens are supported, which will have the following model names listed in the CK_TOKEN_INFO structure:

Model name GID Custom Ability Secure storage instance ID Supported hardware, safety or dynamic Notes
NVPKCS11_FSI_DYNAMIC_1_MODEL_NAME 6002 nvtzvault/pkcs11ks_dynamic_token_1_ability nvtzvault/crypto_ability 1 FSI, dynamic
NVPKCS11_CCPLEX_SAFETY_2_MODEL_NAME 6003 nvtzvault/pkcs11ks_safety_token_2_ability nvtzvault/crypto_ability nvvse/Engines:0-2 2

CCPLEX,

safety

Safety equivalent of original single token
NVPKCS11_CCPLEX_DYNAMIC_2_MODEL_NAME 6004 nvtzvault/pkcs11ks_dynamic_token_2_ability nvtzvault/crypto_ability nvvse/Engines:0-2 2 CCPLEX, dynamic Functionality equivalent to original single token
NVPKCS11_TSEC_SAFETY_3_MODEL_NAME 6005 nvtzvault/pkcs11ks_safety_token_3_ability nvtzvault/crypto_ability nvvse/Engines:6 3 TSEC, safety
NVPKCS11_TSEC_DYNAMIC_3_MODEL_NAME 6006 nvtzvault/pkcs11ks_dynamic_token_3_ability nvtzvault/crypto_ability nvvse/Engines:6 3 TSEC, dynamic
NVPKCS11_CCPLEX_SAFETY_4_MODEL_NAME 6007 nvtzvault/pkcs11ks_safety_token_4_ability nvtzvault/crypto_ability nvvse/Engines:0-2 4 CCPLEX, safety
NVPKCS11_CCPLEX_DYNAMIC_4_MODEL_NAME 6008 nvtzvault/pkcs11ks_dynamic_token_4_ability nvtzvault/crypto_ability nvvse/Engines:0-2 4 CCPLEX, dynamic
NVPKCS11_CCPLEX_SAFETY_5_MODEL_NAME 6009 nvtzvault/pkcs11ks_safety_token_5_ability nvtzvault/crypto_ability nvvse/Engines:0-2 5 CCPLEX, safety
NVPKCS11_CCPLEX_DYNAMIC_5_MODEL_NAME 6010 nvtzvault/pkcs11ks_dynamic_token_5_ability nvtzvault/crypto_ability nvvse/Engines:0-2 5 CCPLEX, dynamic
...
NVPKCS11_CCPLEX_SAFETY_13_MODEL_NAME 6025 nvtzvault/pkcs11ks_safety_token_13_ability nvtzvault/crypto_ability nvvse/Engines:0-2 nvtzvault/macsec_tos_ability 13 CCPLEX, safety NVIDIA reserved for MACSEC
NVPKCS11_CCPLEX_DYNAMIC_13_MODEL_NAME 6026 nvtzvault/pkcs11ks_dynamic_token_13_ability nvtzvault/crypto_ability nvvse/Engines:0-2 nvtzvault/macsec_tos_ability 13 CCPLEX, dynamic NVIDIA reserved for MACSEC
NVPKCS11_CCPLEX_SAFETY_14_MODEL_NAME 6027 nvtzvault/pkcs11ks_safety_token_14_ability nvtzvault/crypto_ability nvvse/Engines:0-2 14 CCPLEX, safety NVIDIA reserved for Drive Update
NVPKCS11_CCPLEX_DYNAMIC_14_MODEL_NAME 6028 nvtzvault/pkcs11ks_dynamic_token_14_ability nvtzvault/crypto_ability nvvse/Engines:0-2 14 CCPLEX, dynamic NVIDIA reserved for Drive Update

The PKCS#11 sample app demonstrates how to use C_GetTokenInfo to identify and open a token that matches that name (NVPKCS#11_CCPLEX_DYNAMIC_2_MODEL_NAME).

Accessing the Token

To use a token, your application must have access to both keys in a persistent storage area and access to cryptographic hardware engines. The permissions for these are handled using GIDs and QNX custom abilities.

There are 27 unique key storage area custom abilities, one for each of the supported tokens.

There is 1 nvtzvault/crypto_ability custom ability required by every PKCS#11 library application.

To use a CCPLEX token, your application must also have access permission to all three GP-SE channels, by adding nvvse/Engines:0-2 custom abilities.

To use a TSEC token the application requires nvvse/Engines:6 custom ability.

For an application using a CCPLEX token to also have access to the TZ-SE cryptographic hardware, you add nvvse/Engines:3-5 custom abilities.

The PKCS#11 sample app README file demonstrates how to run the sample app as non-root with correct custom ability to use NVPKCS11_CCPLEX_DYNAMIC_2_MODEL_NAME.

Note: The existing client application code must be updated to choose a token explicitly and to use the new GIDs and custom abilities.

Choosing the Token

If your application is safety related, it should use a safety token. This is to prevent interference from any other applications or updates.

If your application needs to update objects in secure storage, it will need to use a dynamic token. Note that the safety token will not see those changes until after a reboot or an SC7 cycle has taken place.

If your application requires access to persistently stored objects, and also requires that those objects are not accessible to any other applications, then use a unique secure storage instance ID.

The following example shows how secure storage updates can be performed, and also how the isolation between safety and dynamic tokens works.

Step 1

System is powered off. Secure storage for ID 4 contains four keys.

Step 2

Power on. System boots. Two PKCS11 tokens are created for CCPLEX hardware with secure storage ID 4.

Each token contains a copy of the secure storage content.

Step 3

A safety critical application connects to the CCPLEX_SAFETY_4 token, and starts to use key 1 for an operation.

Step 4

An update app connects to CCPLEX_DYNAMIC_4. This is app is not safety critical. It also uses key 1.

Step 5

The update app needs to replace key 1. It will begin by deleting that key. Note that the original key still exists in the safety token, and in secure storage.

The safety app continues to function without interruption.

Step 6

A new key (5) is added to CCPLEX_DYNAMIC_4. The new key is visible to any app that uses the CCPLEX_DYNAMIC_4 token.

The CCPLEX_SAFETY_4 token has no way to see this key. It is not yet in secure storage, so would be lost if a reboot were to happen.

Step 7

The update app now checks that key 5 is functional by performing some operations with it.

Secure storage cannot be updated yet, as the safety app is still using CCPLEX_SAFETY_4.

Step 8

Safety app has terminated. The update app then commits the changes to secure storage by calling C_NVIDIA_CommitTokenObjects().

Step 9

A reboot then takes place. Key 1 is no longer usable by CCPLEX_SAFETY_4 or CCPLEX_DYNAMIC_4, and both tokens can use key 5.

Multi-Threaded Application

PKCS#11 library only supports multi-threaded access by an application using the native operating system primitives.

Session Type

PKCS#11 library supports read/write (R/W) user sessions on dynamic tokens, and read-only (R/O) user sessions on all tokens. To update secure storage in a R/W session, C_NVIDIA_CommitTokenObjects() must be called as outlined previously.

Active Operation Abandonment

PKCS#11 library fails any cryptographic initialization functions for a session if there are any active operations of the same type on that session.​ The active operation will reset and return to the idle state.

PKCS#11 library additionally allows C_MessageSignInit and C_MessageVerifyInit to be called with pMechanism set to NULL_PTR to terminate an active operation

.

Operations That Cannot Be Canceled by C_SessionCancel

PKCS#11 library shall return CKR_OPERATION_CANCEL_FAILED if any of the following operations are included in the request to C_SessionCancel:

  • CKF_GENERATE_KEY_PAIR
  • CKF_GENERATE
  • CKF_WRAP
  • CKF_UNWRAP
  • CKF_DERIVE

User Type

PKCS#11 library only supports the user type: normal user.

Read-Only User Authentication

PKCS#11 library supports normal user login to a read only session without the need for a PIN.

pPin from client application is NULL_PTR.

Read/Write User Authentication

PKCS#11 library supports login of an authenticated normal user login to a Read/Write session without the need for a PIN.

pPin from client application is NULL_PTR.

Encrypt Input Data Length

PKCS#11 library restricts the data length of all multi-part encrypt update operations using CKM_AES_CBC_PAD mechanism to be a multiple of the cryptographic operation block size. The exception is the last encrypt update part, which does not have to be a multiple of the block size.

Encrypt operations using CKM_AES_CTR mechanism restricts data length to multiples of 16 bytes only.

Decrypt Input Data length

PKCS#11 library restricts the data length of multi-part decrypt update operations to be a multiple of the cryptographic operation block size.

Decrypt operations using CKM_AES_CTR mechanism restricts data length to multiples of 16 bytes only.

Session Object Limit

PKCS#11 library restricts the number of session objects that may be created, generated, derived, or unwrapped across all sessions of a single application to a total of 88 keys split as 64 secret, 8 RSA public, 8 EC public and 8 EC private keys and 8 data objects, subject to the support of those objects by the tokens in use.

Cryptoki Function Calls

PKCS#11 library does not support every function in the Cryptoki API. It has a stub for every unsupported function and returns the value CKR_FUNCTION_NOT_SUPPORTED.

Callback Function Not Supported

PKCS#11 library does not support surrender callbacks.

Find Key by ID and Class

PKCS#11 library restricts key object search to the template attribute CKA_ID and CKA_CLASS only.

Deriving Additional Key

PKCS#11 library limits key derivation to a single derived key per one C_DeriveKey() call.

Derivation From Fuse-based Keys

The support for NV_OEM_KEY1 and NV_OEM_KEY2 for key derivation using SP800-108-Counter-KDF-HMAC-SHA256(Key=FUSE_KEYS_KDK0_0_0 (ODM_KDK0), L=256, Label=<as_required>, Context=<as_required>) scheme has been added. Refer to the following table for derivation data values. The purpose of these key is set to HMAC in the key manifest, meaning the API is responsible for preparing the input in the format mentioned in the scheme. PKCS#11 Library provides interfaces for key derivation using these two keys.

The two (2) keys (NV_OEM_KEY1 and NV_OEM_KEY2) are derived from ODM_KDK0 using the same SP800-108-Counter-KDF-HMAC-SHA256 scheme. However, the two keys are different in the sense that the label and context used to derive these keys from ODM_KDK0 are different. While NV_OEM_KEY1 is same for all devices, if ODM KDK0 is a class key i.e. same for all devices, NV_OEM_KEY2 is a device-specific key as Exclusive Chip ID (ECID), which is unique to each device, is used as the context for the derivation of this key.

Fused Key Hierarchy

Refer below for derivation data values of NV_OEM_KEY1 and NV_OEM_KEY2

PRF Input Data Field Identifier Format Value

[i]

CK_SP800_108_ITERATION_VARIABLE

Big Endian 32 bit integer

Value for NV_OEM_KEY1 & NV_OEN_KEY2 is 0x00000001

Label

CK_SP800_108_BYTE_ARRAY

1 to 32 bytes

NV_OEM_KEY1 - "NV_OEM_DERIVED_1"NV_OEM_KEY2 - "NV_OEM_DERIVED_2"

0x00

CK_SP800_108_BYTE_ARRAY

1 byte

"00" in HexString Format

Context

CK_SP800_108_BYTE_ARRAY

1 to 32 bytes

Value for NV_OEM_KEY1 - "00" in HexString Format and size is 1 Byte

Value for NV_OEM_KEY2 - <ECID in HexString Format> and size is 16 Bytes

[L]

CK_SP800_108_DKM_LENGTH

Big Endian 32 bit integer

Key Length for NV_OEM_KEY1 and NV_OEM_KEY2 will be 256 bits, value is 0x00000100

PKCS#11 library supports derivation from the following named fuse-based keys:

CKA_ID

"NV_OEM_KEY1                     "

A general purpose OEM-defined key
"NV_OEM_KEY2                     " A general purpose device-unique key

CKM_SP800_108_COUNTER_KDF Input Parameters

PKCS#11 library limits the counter mode key derivation function, denoted CKM_SP800_108_COUNTER_KDF, to use the following PRF input data definitions.

SP800-108 section 5.1 outlines a sample Counter Mode KDF, which defines the following PRF input:

PRF (KI, [i] || Label || 0x00 || Context || [L])

where || is the concatenation operation in which the order of the values are defined and KI is the base key being derived from.

The following table lists the PRF input data field types, meanings, limitations, and order that are supported within the CK_PRF_DATA_PARAM structure:

PRF Input Data Field Identifier Format Description Comment

[i]

CK_SP800_108_ITERATION_VARIABLE

Big Endian 8 or 32 bits wide

Counter integer that is the iteration variable.  Value shall be 1 for SHA_256_HMAC or AES_CMAC PRF

Default: Use 32 bits wide. 8 bits wide support is for MACSEC wpa-supplicant application

Label

CK_SP800_108_BYTE_ARRAY

1 to 32 bytes

Client Application supplied byte array that identifies the purpose for the derived keying material. The byte 0x00 is not allowed.

0x00

CK_SP800_108_BYTE_ARRAY

1 byte

An all zero octet. Used to indicate a separation of different variable length data fields

Context

CK_SP800_108_BYTE_ARRAY

1 to 32 bytes

Client Application supplied byte array containing the information related to the derived key. The byte 0x00 is not allowed.

[L]

CK_SP800_108_DKM_LENGTH

Big Endian 16 or 32 bits wide

An integer specifying the length (in bits) of the derived key. 

Default: Use 32 bits wide. 16 bits wide support is for MACSEC wpa-supplicant application

Secret Key Material Protection

PKCS#11 library does not allow access to secret key material or secret key check value.

Added Allowed Function Return Values

PKCS#11 library allows CKR_OPERATION_ACTIVE return value for C_Digest, C_Encrypt, and C_Decrypt functions. The current operation will reset and return to idle state upon returning CKR_OPERATION_ACTIVE. The approach taken warns of a potential programming error rather than silently accepting it.

PKCS#11 library allows CKR_MECHANISM_INVALID return value for C_xxUpdate, C_xxFinal if C_xxInit is called with mechanism CKM_AES_GCM.

PKCS#11 library allows CKR_OPERATION_NOT_INITIALIZED return value for C_xxMessageBegin, C_EncryptMessage functions.

PKCS#11 library allows CKR_OPERATION_ACTIVE return value for C_xxMessageNext, C_EncryptMessage, C_DecryptMessage functions. The current operation will reset and return to idle state upon returning CKR_OPERATION_ACTIVE. The approach taken warns of a potential programming error rather than silently accepting it.

PKCS#11 library allows CKR_SESSION_READ_ONLY_EXISTS return value for C_OpenSession function.

PKCS#11 library allows CKR_ARGUMENTS_BAD return value for C_EncryptMessageBegin function.

PKCS#11 library allows CKR_MECHANISM_INVALID return value for C_xxMessageBegin functions.

PKCS#11 library allows CKR_FUNCTION_NOT_SUPPORTED return value for C_SignUpdate, C_VerifyUpdate and C_VerifyFinal functions.

Symmetric Key Block Mode

When using PKCS#11 APIs to generate, derive, or unwrap symmetric keys, users of DRIVE OS must specify at most one block mode in the CKA_ALLOWED_MECHANISMS template attribute for any particular key.

Exception: Specifying CKM_AES_CBC and CKM_AES_CBC_PAD for the same key is acceptable.

CMAC Message Length

PKCS#11 library does not support Signature requests using CKM_AES_CMAC with a 0 (zero)-length message.

Mutually Exclusive KDF Mechanism Support

When using PKCS#11 APIs to derive from a base key, that base key can support either one of CKM_SP800_108_COUNTER_KDF or CKM_NVIDIA_SP800_56c_TWO_STEPS_KDF but not both together.

C_Finalize Prior to SC7 Entry

All applications that use PKCS#11 library must call C_Finalize prior to SC7 entry. If this is not done, then you will receive unexpected errors when attempting to use PKCS#11 APIs.