IBM-specific post quantum mechanisms
View detailed descriptions about the purpose and availability of all IBM®-specific post quantum cryptography mechanisms.
openCryptoki provides multiple IBM-specific post quantum cryptography mechanisms. Read information about the mechanisms based on the standardized versions of ML-KEM and ML-DSA. Information about predecessor mechanisms for Kyber and Dilithium is provided as well.
| Mechanism and Reference | Enc & Dec | Sign & Verify | SR & VR | Digest | Gen. Key/Key Pair | Wrap & Unwrap | Derive |
|---|---|---|---|---|---|---|---|
| CKM_IBM_ML_DSA, see CKM_IBM_ML_DSA | |||||||
| CKM_IBM_ML_DSA_KEY_PAIR_GEN, see CKM_IBM_ML_DSA_KEY_PAIR_GEN | |||||||
| CKM_IBM_ML_KEM, see CKM_IBM_ML_KEM | |||||||
| CKM_IBM_ML_KEM_KEY_PAIR_GEN, see CKM_IBM_ML_KEM_KEY_PAIR_GEN | |||||||
| CKM_IBM_DILITHIUM, see CKM_IBM_DILITHIUM | ✔ | ✔ | |||||
| CKM_IBM_KYBER, see CKM_IBM_KYBER | ✔ | ✔ | ✔ |
Common information for post-quantum ML-KEM and ML-DSA operations
With openCryptoki version 3.26, the CCA token, the EP11 token, and the Soft token support the following new standardized versions of post-quantum cryptographic operations:
- Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM): This is a post-quantum key encapsulation mechanism (KEM) standardized by NIST. It is used to protect symmetric keys for encrypting and decrypting data. It is the final and standardized version of Kyber according to FIPS 203.
- Module-Lattice-Based Digital Signature Algorithm (ML-DSA): This is a post-quantum digital signature algorithm standardized by NIST. It is the final and standardized version of Dilithium according to FIPS 204.
Prerequisites for the CCA token:
Prerequisites for the EP11 token and Soft token:
For the EP11 token, an updated EP11 card firmware and host library version is required that supports the CEX8P cryptographic coprocessor.
For the Soft token, the support is based on the Open Quantum Safe provider for OpenSSL (OQS provider, see https://github.com/open-quantum-safe/oqs-provider) implementing the ML-DSA and ML-KEM algorithms for OpenSSL. Alternatively, starting with OpenSSL version 3.5.0, ML-DSA and ML-KEM are built in into OpenSSL. Older versions of the OQS-provider only support the older variants (Dilithium/Kyber round 3), while the never versions only support the final ML-DSA and ML-KEM variants.
CKM_IBM_ML_KEM
Availability:
The CKM_IBM_ML_KEM mechanism is available with the CCA token, EP11 token, and the Soft token.
Description:
CKM_IBM_ML_KEM_KEY_PAIR_GEN
Availability:
The CKM_IBM_ML_KEM_KEY_PAIR_GEN mechanism is available with the CCA token, EP11 token, and the Soft token.
Description:
CKM_IBM_ML_DSA
Availability:
The CKM_IBM_ML_DSA mechanism is available with the CCA token, EP11 token, and the Soft token.
Description:
CKM_IBM_ML_DSA_KEY_PAIR_GEN
Availability:
The CKM_IBM_ML_DSA_KEY_PAIR_GEN mechanism is available with the CCA token, EP11 token, and the Soft token.
Description:
CKM_IBM_DILITHIUM
Availability:
The CKM_IBM_DILITHIUM mechanism is available with the EP11 token, the CCA token and the Soft token.
Description:
Dilithium is a post-quantum signature scheme. That is, it can generate signatures that resist attacks from quantum computers, but also from classical computers. Dilithium is one of the candidate algorithms submitted to the NIST post-quantum cryptography project.
The CCA, EP11, and Soft tokens provide one single mechanism for three operations: key generation, sign, and verify. Soft tokens additionally require an OQS provider which still supports Dilithium.
With the EP11 token, you can also import and export Dilithium keys by wrapping or unwrapping them using AES or TDES key encrypting keys (KEKs). That is, you can protect Dilithium keys that are sent to another system, received from another system, or stored with data in a file. Use any mechanism to wrap or unwrap IBM Dilithium keys that is convenient for your purposes, for example:
- CKM_AES_CBC_PAD
- CKM_DES3_CBC_PAD
On the TKE workstation, you must enable Dilithium processing by setting domain (access) control point 65 on the used cryptographic coprocessors :
65 XCP_CPB_ALG_PQC enable support for post quantum cryptographic algorithms
The CCA token supports to import Dilithium keys from clear key values, as well as to import and export an existing CCA secure key token (key blob) via the CKA_IBM_OPAQUE attribute.
Due to the large key sizes, the CCA token does not support to wrap or unwrap Dilithium keys.
Prerequisites:
Using the CKM_IBM_DILITHIUM mechanism requires the following prerequisites:
- EP11 token: For Dilithium (6,5) Round 2, the EP11 host library 3.0 or later is required. For all other IBM Dilithium keys available with openCryptoki 3.20 or later, the EP11 host library 4.0 or later is required.
- CCA token: CCA release 7.1 and later is required to support Dilithium (6,5) Round 2. CCA release 8.0 and later is required to support Dilithium (8,7) Round 2, Dilithium (6,5) Round 3, and Dilithium (8,7) Round 3.
- If a Dilithium key is to be generated that is not supported by the used token, then the key generation fails with error code CKR_KEY_SIZE_RANGE.
- A Crypto Express7S feature or later, configured as Crypto Express EP11 coprocessor (CEX7P) with firmware level 7.15 or later
- Not all firmware versions of EP11 cryptographic coprocessors support all Round 2 and Round 3 variants. Thus, a specific variant can only be used when all APQNs configured for the EP11 token support the desired variant. The EP11 token checks if all configured APQNs support the desired variant, and only then it allows to generate, import, or use an IBM Dilithium key with the desired variant.
Key type:
The IBM-specific key type for an IBM Dilithium key object is:
#define CKK_IBM_PQC_DILITHIUM CKK_VENDOR_DEFINED + 0x10023
#define CKK_IBM_DILITHIUM CKK_IBM_PQC_DILITHIUM
Key form:
The EP11 host library uses the following key form for IBM Dilithium public and private keys:
- Public key
DilithiumPublicKey ::= BIT STRING { SEQUENCE { rho BIT STRING, [2] -- nonce t1 BIT STRING [3] -- from vector(L) } } - Private key
DilithiumPrivateKey ::= SEQUENCE { version INTEGER, -- v0, reserved 0 rho BIT STRING, -- nonce key BIT STRING, -- key/seed/D tr BIT STRING, -- PRF bytes (’CRH’ in specification) s1 BIT STRING, -- vector(L) s2 BIT STRING, -- vector(K) t0 BIT STRING, -- low bits(vector L) t1 [0] IMPLICIT OPTIONAL { t1 BIT STRING, -- high bits(vector L) -- see also public key/SPKI } }
The currently supported key forms are:
| OID | Key form and value | Meaning |
|---|---|---|
| 1.3.6.1.4.1.2.267.1.6.5 | CK_IBM_DILITHIUM_KEYFORM_ROUND2_65 = 1 (Alias: IBM_DILITHIUM_KEYFORM_ROUND2) | Round 2 dilithium-high |
| 1.3.6.1.4.1.2.267.1.8.7 | CK_IBM_DILITHIUM_KEYFORM_ROUND2_87 = 2 | Round 2 dilithium-87 |
| 1.3.6.1.4.1.2.267.7.4.4 | CK_IBM_DILITHIUM_KEYFORM_ROUND3_44 = 3 | Round 3 dilithium-r3-weak |
| 1.3.6.1.4.1.2.267.7.6.5 | CK_IBM_DILITHIUM_KEYFORM_ROUND3_65 = 4 | Round 3 dilithium-r3-rec |
| 1.3.6.1.4.1.2.267.7.8.7 | CK_IBM_DILITHIUM_KEYFORM_ROUND3_87 = 5 | Round 3 dilithium-r3-vhigh |
Attributes:
| Attribute | Data type | Meaning |
|---|---|---|
| CKA_IBM_DILITHIUM_KEYFORM (CKA_VENDOR_DEFINED + 0xd0001) | CK_ULONG | The Dilithium key form, currently Round 2 and Round 3. Can be one of the following:
|
| CKA_IBM_DILITHIUM_MODE (CKA_VENDOR_DEFINED + 0x10) | CK_BYTE | Specifies the OID of the Dilithium variant used as byte array. |
| CKA_IBM_DILITHIUM_RHO (CKA_VENDOR_DEFINED + 0xd0002) | CK_BYTE | The private rho key component |
| CKA_IBM_DILITHIUM_SEED (CKA_VENDOR_DEFINED + 0xd0003) | CK_BYTE | The private seed key component |
| CKA_IBM_DILITHIUM_TR (CKA_VENDOR_DEFINED + 0xd0004) | CK_BYTE | The private tr key component |
| CKA_IBM_DILITHIUM_S1 (CKA_VENDOR_DEFINED + 0xd0005) | CK_BYTE | The private s1 key component |
| CKA_IBM_DILITHIUM_S2 (CKA_VENDOR_DEFINED + 0xd0006) | CK_BYTE | The private s2 key component |
| CKA_IBM_DILITHIUM_T0 (CKA_VENDOR_DEFINED + 0xd0007) | CK_BYTE | The private t0 key component |
| CKA_IBM_DILITHIUM_T1 (CKA_VENDOR_DEFINED + 0xd0008) | CK_BYTE | The public t1 key component |
| CKA_VALUE | CK_BYTE | For a public Dilithium key, this attribute contains the BER encoded SPKI of the public key. For a private Dilithium key, it contains the PKCS#8 encoded private key value in case of clear key import, otherwise it is empty. |
PKCS #11 Cryptographic Token Interface Base Specification Version 3.0.
When generating Dilithium keys, an application can specify the CKA_IBM_DILITHIUM_KEYFORM or CKA_IBM_DILITHIUM_MODE attribute and thus select the variant to be used. For backward compatibility, if neither the CKA_IBM_DILITHIUM_KEYFORM nor CKA_IBM_DILITHIUM_MODE attribute is specified, it defaults to IBM_DILITHIUM_KEYFORM_ROUND2_65.
Key generation and unwrap operations supply the public Dilithium key attributes CKA_IBM_DILITHIUM_RHO and CKA_IBM_DILITHIUM_T1, as well as attributes CKA_IBM_DILITHIUM_KEYFORM and CKA_IBM_DILITHIUM_MODE to both, the public and the private key.
The SPKI is supplied in attribute CKA_VALUE to the public key.
When importing Dilithium keys from clear key values, you have two options:
- Specify the CKA_IBM_DILITHIUM_KEYFORM or CKA_IBM_DILITHIUM_MODE attribute together with the other public or private Dilithium key attributes. In this case, openCryptoki supplies the SPKI in the CKA_VALUE attribute to the public key during import.
- Specify the CKA_VALUE attribute to contain the SPKI or PKCS#8 encoding of the public or private key to import. In this case, CKA_IBM_DILITHIUM_KEYFORM and CKA_IBM_DILITHIUM_MODE must not be specified, since the OID is contained within the SPKI and PKCS#8 encoded key material.
Attributes CKA_IBM_DILITHIUM_KEYFORM and CKA_IBM_DILITHIUM_MODE are supplied to both, the public key and the private key during import.
The different Dilithium variants have different cryptographic strengths associated. The strength calculation used for openCryptoki policies and statistics take the used variant into consideration.
Functions for IBM Dilithium key creation and unwrapping:
Use function C_GenerateKeyPair() to create an IBM Dilithium key object consisting of a public/private key pair. Note that the CKM_IBM_DILITHIUM mechanism has no mechanism-specific parameters. The following is a sample for key object creation:
CK_BBOOL true = CK_TRUE;
CK_ATTRIBUTE public_template[] = {
{CKA_VERIFY, &true, sizeof(true)},
};
CK_ATTRIBUTE private_template[] = {
{CKA_SIGN, &true, sizeof(true)},
};
CK_MECHANISM mech;
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE publ_key = CK_INVALID_HANDLE, priv_key = CK_INVALID_HANDLE;
...
mech.mechanism = CKM_IBM_DILITHIUM;
mech.ulParameterLen = 0;
mech.pParameter = NULL;
CK_RV rv;
rv = C_GenerateKeyPair(session, &mech,
public_template, 1,
private_template, 1,
&publ_key, &priv_key);
if (rv == CKR_OK) {
...
}
Use functions C_WrapKey() and C_UnwrapKey() if you need to transport IBM Dilithium keys. See the following sample of an unwrapping operation:
CK_MECHANISM wrap_mech;
CK_OBJECT_HANDLE secret_key = CK_INVALID_HANDLE;
CK_BYTE_PTR wrapped_key = NULL;
CK_ULONG wrapped_keylen;
CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE;
CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
CK_KEY_TYPE key_type = CKK_IBM_PQC_DILITHIUM;
CK_OBJECT_HANDLE priv_key = CK_INVALID_HANDLE;
CK_BYTE unwrap_label[] = "unwrapped_private_Dilithium_Key";
CK_BBOOL true = TRUE;
CK_RV rv;
CK_ATTRIBUTE unwrap_tmpl[] = {
{CKA_CLASS, &class, sizeof(class)},
{CKA_KEY_TYPE, &key_type, sizeof(key_type)},
{CKA_TOKEN, &true, sizeof(true)},
{CKA_LABEL, &unwrap_label, sizeof(unwrap_label)},
{CKA_SENSITIVE, &true, sizeof(true)},
{CKA_DECRYPT, &true, sizeof(true)},
{CKA_SIGN, &true, sizeof(true)},
};
wrap_mech.mechanism = CKM_AES_CBC_PAD;
wrap_mech.pParameter = "0123456789abcdef";
wrap_mech.ulParameterLen = 16;
/* Generate wrapping key */
...
/* Wrap Dilithium key with wrapping key */
...
/* Unwrap Dilithium key */
rv = funcs->C_UnwrapKey(session, &wrap_mech, secret_key,
wrapped_key, wrapped_keylen,
unwrap_tmpl,
sizeof(unwrap_tmpl) / sizeof(CK_ATTRIBUTE),
&priv_key);
if (rv != CKR_OK) {
...
}
Restrictions for using IBM Dilithium keys:
- IBM Dilithium keys cannot actively be used to transport (wrap and unwrap) other keys, but they can be wrapped and unwrapped for being transported using standard key types (AES, TDES).
- IBM Dilithium keys cannot be derived from given keys. They can only be generated or imported from given key values.
- Only SignInit() and Sign() (single-part operations) is supported by the EP11 host library. SignUpdate() and SignFinal() functions are not supported. The same restrictions apply for verify operations accordingly.
CKM_IBM_KYBER
Availability:
The CKM_IBM_KYBER mechanism is available with the EP11 token.
Description:
You can use this mechanism to generate quantum-safe Kyber key pairs as well as to perform encryption and decryption operations using Kyber keys. In addition, this mechanism offers methods to encapsulate or decapsulate (wrap or unwrap) keys (key encapsulation methods, KEM) which you can use to create shared secrets between to communicating parties.
On the TKE workstation, you must enable Kyber processing by setting domain (access) control point 65 on the used cryptographic coprocessors :
65 XCP_CPB_ALG_PQC enable support for post quantum cryptographic algorithms
Prerequisites:
Using the CKM_IBM_KYBER mechanism has the following prerequisites:
- The EP11 host library 4.0 or later is required.
- A Crypto Express8S feature, configured as Crypto Express EP11 coprocessor (CEX8P) with firmware level 8.9 or later is required.
- Not all firmware versions of EP11 cryptographic coprocessors support all Round 2 and Round 3 variants. Thus, a specific variant can only be used when all APQNs configured for the EP11 token support the desired variant. The EP11 token checks if all configured APQNs support the desired variant, and only then it allows to generate, import, or use an IBM Kyber key with the desired variant.
- If a Kyber key is to be generated that is not supported by the token, then the key generation fails with error code CKR_KEY_SIZE_RANGE.
Key type:
The IBM-specific key type for an IBM Kyber key object is:
#define CKK_IBM_PQC_KYBER CKK_VENDOR_DEFINED + 0x00010024
#define CKK_IBM_KYBER CKK_IBM_PQC_KYBER
Key form:
Kyber keys consist of a private key component sk and public key component pk, as defined by the ANS1 encodings:
KyberPublicKey ::= BIT STRING {
SEQUENCE {
pk BIT STRING -- public key
}
}
KyberPrivateKey := SEQUENCE {
version INTEGER, -- v0; reserved 0
sk BIT STRING -- secret key material
[0] IMPLICIT OPTIONAL {
pk||rs BIT STRING
-- public key (pk) concatenated with 2x32 bytes rs (rs = 64 times 0x30)
}
}
The currently supported key forms are:
| OID | Key form and value | Meaning |
|---|---|---|
| 1.3.6.1.4.1.2.267.5.3.3 | CK_IBM_KYBER_KEYFORM_ROUND2_768 = 1 | Round 2 Kyber-r2rec |
| 1.3.6.1.4.1.2.267.5.4.4 | CK_IBM_KYBER_KEYFORM_ROUND2_1024 = 2 | Round 2 Kyber-r2high |
Attributes:
According to the key components, the following Kyber key component attributes are defined:
| Attribute | Data type | Meaning |
|---|---|---|
| CKA_IBM_KYBER_KEYFORM (CKA_VENDOR_DEFINED + 0x000d0009) | CK_ULONG | The Kyber key form, currently Round 2. Can be one of the following:
|
| CKA_IBM_KYBER_MODE (CKA_VENDOR_DEFINED + 0x0000000E) | CK_BYTE | Specifies the OID of the Kyber variant used as byte array. |
| CKA_IBM_KYBER_PK (CKA_VENDOR_DEFINED + 0x000d000A) | CK_BYTE | public Kyber key component |
| CKA_IBM_KYBER_SK (CKA_VENDOR_DEFINED + 0x000d000B) | CK_BYTE | private Kyber key component |
When generating Kyber keys, an application can specify the CKA_IBM_KYBER_KEYFORM or CKA_IBM_KYBER_MODE attribute and thus select the variant to be used. If neither the CKA_IBM_KYBER_KEYFORM nor CKA_IBM_KYBER_MODE attribute is specified, it defaults to CK_IBM_KYBER_KEYFORM_ROUND2_HIGH.
Key generation and unwrap operations supply the public Kyber key attribute CKA_IBM_KYBER_PK, as well as attributes CKA_IBM_KYBER_KEYFORM and CKA_IBM_KYBER_MODE to both, the public and the private key.
The SPKI is supplied in attribute CKA_VALUE to the public key.
When importing Kyber keys from clear key values, an application must either specify the CKA_IBM_KYBER_KEYFORM attribute together with the other public or private Kyber key attribute(s), or the application must specify CKA_VALUE containing the SPKI or PKCS#8 encoding of the public or private key to import. In this case, CKA_IBM_KYBER_MODE must not be specified, since the OID is contained within the SPKI and PKCS#8 encoded key material.
Import supplies the SPKI in CKA_VALUE to the public key, if the public key is imported from the individual Kyber key component attributes. Attributes CKA_IBM_KYBER_KEYFORM and CKA_IBM_KYBER_MODE are supplied to both, the public key and the private key during import.
Kyber offers both encryption/decryption and encapsulation/decapsulation mechanisms.
Encapsulation or decapsulation mechanisms, also summarized by the term key encapsulation mechanisms (KEM) can be used for creating shared secrets between two parties. Respective functionality is implemented using the C_DeriveKey() interface for key encapsulation and decapsulation.
The base key argument to C_DeriveKey() is either a public or a private Kyber key, respectively. Encapsulation generates a new secret and encrypts it using Kyber encryption. Both, the cipher text used for exchanging the generated secret as well as a handle of a new key are output from the encapsulation operation.
Kyber KEM functions
Use the following functions and parameters for Kyber KEM processing.
#define CKD_IBM_HYBRID_NULL CKD_VENDOR_DEFINED + 0x00000001UL
#define CKD_IBM_HYBRID_SHA1_KDF CKD_VENDOR_DEFINED + 0x00000002UL
#define CKD_IBM_HYBRID_SHA224_KDF CKD_VENDOR_DEFINED + 0x00000003UL
#define CKD_IBM_HYBRID_SHA256_KDF CKD_VENDOR_DEFINED + 0x00000004UL
#define CKD_IBM_HYBRID_SHA384_KDF CKD_VENDOR_DEFINED + 0x00000005UL
#define CKD_IBM_HYBRID_SHA512_KDF CKD_VENDOR_DEFINED + 0x00000006UL
Structure for Kyber KEM parameters:
typedef struct CK_IBM_KYBER_PARAMS {
CK_ULONG ulVersion;
CK_IBM_KYBER_KEM_MODE mode;
CK_IBM_KYBER_KDF_TYPE kdf;
CK_BBOOL bPrepend;
CK_BYTE *pCipher;
CK_ULONG ulCipherLen;
CK_BYTE *pSharedData;
CK_ULONG ulSharedDataLen;
CK_OBJECT_HANDLE hSecret;
} CK_IBM_KYBER_PARAMS;
The mechanism parameter CK_IBM_KYBER_PARAMS is used with the C_DeriveKey() function to provide Kyber-KEM parameters. For encapsulation with a public key, field mode is set to CK_IBM_KYBER_KEM_ENCAPSULATE. Fields pCipher and ulCipherLen are output in this case, and must specify a buffer large enough to hold the returned cipher text. A symmetric key with a key type according to attribute CKA_KEY_TYPE in the derive template is returned, together with the cipher text in field pCipher. Field ulCipherLen is updated to hold the size of the returned cipher text. If the supplied cipher text buffer is too small to hold the returned cipher text, CKR_BUFFER_TOO_SMALL is returned.
For decapsulation with a private key, field mode is set to CK_IBM_KYBER_KEM_DECAPSULATE. Fields pCipher and ulCipherLen are input in this case and must specify the cipher text that was generated by the encapsulation step. A symmetric key with a key type according to attribute CKA_KEY_TYPE in the derive template is returned.
Hybrid key generation or derivation can be performed to concatenate multiple secrets into a generic secret key.
Initialize a hybrid secret using either an ECDH key derivation, or a Kyber KEM using CKD_IBM_HYBRID_NULL as key derivation function (KDF) in field kdf of CK_IBM_KYBER_PARAMS or CK_ECDH1_DERIVE_PARAMS.
It can then be concatenated with other secrets using Kyber KEM by specifying the hybrid secret in field hSecret together with a CKD_IBM_HYBRID_SHAxxx key derivation function in field kdf, and set field bPrepend to CK_TRUE to prepend the secret specified in hSecret with the Kyber secret. Or set the bPrepend field to CK_FALSE to concatenate the two secrets the other way round. Optionally you can specify additional shared data in fields pSharedData and ulSharedDataLen for the ANSI 9.63 key derivation.
For key encapsulation, the derive template for the resulting key must have CKA_EXTRACTABLE = CK_TRUE. All Kyber keys used in the derivation must have CKA_DERIVE = CK_TRUE. Hybrid secrets used in hybrid key derivation must have CKA_IBM_USE_AS_DATA = CK_TRUE.
The different Kyber variants have different cryptographic strength associated. The strength calculation used for openCryptoki policies and statistics must be adjusted to additionally take the used variant or key form into consideration.