Introduction
PKCS#11, also known as "Cryptoki," is a standard API for cryptographic tokens, defining a platform-independent interface to cryptographic devices such as hardware security modules (HSMs) and smart cards. This standard allows applications to interact with cryptographic hardware in a uniform manner, abstracting the details of the underlying hardware.
Purpose and Benefits
PKCS#11 serves as a critical component in securing cryptographic operations by leveraging hardware-based security. It provides a standardized way to:
- Generate, store, and manage cryptographic keys securely.
- Perform cryptographic operations such as encryption, decryption, signing, and verification.
- Ensure that sensitive cryptographic material never leaves the secure hardware environment.
Specifications
The PKCS#11 standard is maintained by the OASIS PKCS 11 Technical Committee. The latest specifications can be found on the OASIS PKCS 11 Technical Committee website.
PKCS#11 Tools & Documentation
- Official Specification: PKCS#11 v2.40
- OASIS PKCS 11 Technical Committee: OASIS PKCS 11 TC
- OpenSC provides a set of libraries and utilities to work with smart cards.
- pkcs11-tool is a command-line utility for performing various PKCS#11 operations. It is part of the OpenSC project and provides a simple interface for tasks such as listing tokens, generating key pairs, and performing cryptographic operations.
- libp11 is a wrapper library for PKCS#11 modules with OpenSSL interface
PKCS#11 on Keros 6
On Keros 6, OP-TEE is used as a backend secure provider and provides a standard PKCS#11 module interface. The PKCS#11 module that interfaces with OP-TEE is located at /usr/lib/libckteec.so.0.
On Keros 6, Kerlink will use PKCS#11 module but it is not yet deployed. Therefore, for compatibility reasons, caution must be taken about modifications made to PKCS#11 slots. There are no issues to use it during development, but we must be careful in production.
The certificate/etc/certs/ztp.pemis used to authenticate with Kerlink services. This certificate will gradually be migrated to OP-TEE PKCS#11 module.
OP-TEE offers 3 slots by default. Kerlink will reserve use of slot 0. The other 2 slots will be free for use.
Example
Activation
To activate PKCS#11 module, you have to install pkcs11-tool with apt install opensc libp11. Once installed, you should be able to list PKCS#11 slot:
root@klk-wifc-030336:~# pkcs11-tool --module /usr/lib/libckteec.so.0 --list-token-slots
Available slots:
Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID 15b45862-2ede-5c56-8899-7af9b86d1303
token state: uninitialized
Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID 15b45862-2ede-5c56-8899-7af9b86d1303
token state: uninitialized
Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID 15b45862-2ede-5c56-8899-7af9b86d1303
token state: uninitialized
You may also list the mechanisms supported by the OP-TEE PKCS#11 module using the command:
root@klk-wifc-030336:~# pkcs11-tool --list-mechanisms --module /usr/lib/libckteec.so.0
To use a PKCS#11 slot, it must first be initialized:
root@klk-wifc-030336:~# pkcs11-tool --module /usr/lib/libckteec.so.0 --slot 1 --init-token --label testtoken --so-pin 12341234
root@klk-wifc-030336:~# pkcs11-tool --list-token-slots --module /usr/lib/libckteec.so.0
Available slots:
Slot 0 (0x0): OP-TEE PKCS11 TA - TEE UUID e6f3ab90-1a46-58ff-a81c-4da2994fdcbd
token label : kerlink
token manufacturer : Linaro
token model : OP-TEE TA
token flags : login required, rng, token initialized, PIN initialized
hardware version : 0.0
firmware version : 0.1
serial num : 0000000000000000
pin min/max : 4/128
Slot 1 (0x1): OP-TEE PKCS11 TA - TEE UUID e6f3ab90-1a46-58ff-a81c-4da2994fdcbd
token label : testtoken
token manufacturer : Linaro
token model : OP-TEE TA
token flags : login required, rng, token initialized
hardware version : 0.0
firmware version : 0.1
serial num : 0000000000000001
pin min/max : 4/128
Slot 2 (0x2): OP-TEE PKCS11 TA - TEE UUID e6f3ab90-1a46-58ff-a81c-4da2994fdcbd
token state: uninitialized
The user PIN must also be initialized:
root@klk-wifc-030336:~# pkcs11-tool --module /usr/lib/libckteec.so.0 --slot 1 --label testtoken --login --so-pin 12341234 --init-pin --pin 12341234
User PIN successfully initialized
The token is now ready for use.
Generate asymmetric keys
We can now generate asymmetric keys, for example with EC keys:
root@klk-wifc-030336:~# pkcs11-tool --module /usr/lib/libckteec.so.0 --token-label testtoken --pin 12341234 --keypairgen --key-type EC:prime256v1 --label ecctest
Key pair generated:
Private Key Object; EC
label: ecctest
Usage: sign, derive
Access: sensitive, always sensitive, never extractable, local
Public Key Object; EC EC_POINT 256 bits
EC_POINT: 04410477229acf1d21d9cfdd1f7192a83b5f0a27fcec03642134bbf544ae693595645898c107fe7bbf462e317c5bcc7aaac1c23e3eedfe2dced8e788dff381b218a709
EC_PARAMS: 06082a8648ce3d030107
label: ecctest
Usage: verify, derive
Access: local
Or with RSA-2048 keys:
root@klk-wifc-030336:~# pkcs11-tool --module /usr/lib/libckteec.so.0 --token-label testtoken --pin 12341234 --key-type rsa:2048 --keypairgen --label rsatest
Key pair generated:
Private Key Object; RSA
label: rsatest
Usage: decrypt, sign
Access: sensitive, always sensitive, never extractable, local
Public Key Object; RSA 2048 bits
label: rsatest
Usage: encrypt, verify
Access: local
Use with OpenSSL
We can also use the PKCS#11 module with OpenSSL. To do this, we need to configure OpenSSL to use the module. This can be done by specifying the PKCS#11 module to use in the configuration. For this, a special configuration file /etc/ssl/kerlink.cnf can be used when invoking OpenSSL.
This way, we can use OpenSSL engines by referring to the engine ID so that it uses the PKCS#11 module mentioned in its configuration. It should be noted that OpenSSL uses PKCS#11 URIs to refer to PKCS#11 objects, unlike pkcs11-tool which uses specific arguments. These URIs follow the format "pkcs11:xxxxxxxx" and adhere to RFC 7512.
For example, to refer to the keys we generated, we simply specify the following URI:
pkcs11:token=testtoken;object=ecc-primev1;type=private
As a result, to use the EC keys with openssl to generate for example a self-signed certificate:
root@klk-wifc-030336:~# export OPENSSL_CONF=/etc/ssl/kerlink.cnf
root@klk-wifc-030336:~# openssl req -new -engine pkcs11 -keyform engine -sha256 -key "pkcs11:token=testtoken;object=ecctest;type=private;pin-value=12341234" -sha256 -out test.pem -subj "/C=CB/O=ME/CN=CN"
To extract the public key:
root@klk-wifc-030336:~# openssl pkey -engine pkcs11 -inform engine -in "pkcs11:token=testtoken;object=rsatest;type=public" -pubout
Other usage
It is also possible to use PKCS#11 with other tools that support it, such as curl, openvpn, or strongswan. Keros basicstation also support using PKCS#11 URIs.