PKCS#11 and OpenCryptoki
PKCS#11 is an application programming interface that defines a general purpose interface to a cryptographic token (a logical view of a cryptographic device).
OpenCryptoki is an open source C based implementation of the PKCS#11 standard interface. Hardware Security Module (HSM) vendors (i.e., IBM) providing a general purpose interface to the cryptographic services of their devices create implementations of PKCS#11 that allow PKCS#11 applications to talk to the respective HSMs.
Reference: https://github.com/opencryptoki/opencryptoki: PKCS#11 library and tools for Linux and AIX. Includes tokens supporting IBM crypto hardware as well as a software token.
Slots and Tokens
Applications access the HSM through tokens. For example, a user of PKCS#11 services from OpenCryptoki when configured with the CCA token will access the CCA co-processor HSM. A PKCS#11 token basically contains objects (i.e. Data Object, Key Object, Certificate Object).
A slot is an entity which stores a token. A slot ID is assigned to each token and used by an application to access the token.
All slots are managed by a daemon called pkcsslotd.
More information can be found in openCryptoki - An Open Source Implementation of PKCS #11 - IBM Documentation

Hands on exercise
This exercise uses OpenSSL with the PKCS#11 provider to access the HSM with CCA firmware via the OpenCryptoki CCA token.
The exercise performs some basic crypto operations (key-generate and sign/verify) with the CCA token via the OpenSSL command line interface.
This is useful for quick demos and prototyping. It could also act as a base for cross-testing.
This exercise can be done on an x86 RHEL system as the CCA token supports x86 starting from OpenCryptoki version 3.24 (OCK_CCA_x86_support)

Provider and Engine interfaces of OpenSSL
OpenSSL has a plugin mechanism which helps to attach to other crypto extensions that OpenSSL doesn’t support natively.
Such a plugin mechanism was previously called Engine before OpenSSL v3.x. Starting from OpenSSL v3.x, the engine interface is deprecated and the new interface is called Provider.
OpenSSL doesn’t support PKCS#11 natively and hence we extend PKCS#11 support to OpenSSL via the PKCS#11 provider.
Setting things up
1)Build openssl git clone https://github.com/openssl/openssl
git checkout openssl-3.5.0
./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl '-Wl,--enable-new-dtags,-rpath,$(LIBRPATH)' --> this is needed so that we don't disturb the current OpenSSL version in the system
make -j$(nproc)
sudo make install -j$(nproc)
2)Build PKCS#11 provider
Follow the steps mentioned in Build_PKCS11_Provider
3)Build OpenCrypotoki
Follow the steps mentioned in Build_OCK
4)Configure OpenSSL to load the PKCS#11 provider
Follow the steps mentioned in Openssl_pkcs11_prov_conf
Once configured, check whether the PKCS#11 provider is listed or not
5)Add CCA
Fetch the CCA download package for your platform and install. This provides the libcsulcca.so and other CCA components.
Export the environment variables CCA_INCLUDE_LOCATION and LD_LIBRARY_PATH
6)Configure the OpenCryptoki token
Follow the steps mentioned in OCK_Token_Config
7)Start the slot daemon as root
sudo pkcsslotd
The exercise
1)View the slots present
We can see that there are a total of 4 slots of which only two slots (slot-2 and slot-3) have tokens present in them (TOKEN_PRESENT attribute)
2)View the tokens present
We can see that there is a CCA token on slot-2 and a soft token on slot-3
3)The different PKCS#11 mechanisms supported by the CCA token can be seen as below:
NOTE: The PKCS#11 provider only supports a limited set of mechanisms (only RSA, EC to be precise). So, OpenSSL can only be used with RSA, EC via the PKCS#11 provider with CCA token even though the CCA token supports many other mechanisms.
4)OpenSSL in action
Generate an RSA key using the p11sak utility (p11sak_utility)
(i)p11sak generate-key rsa 2048 --label "rsa_cca_tok_key" --slot 2
(ii)p11sak list-key all --long --slot 2 --> to know the URI of the key
(iii)/opt/openssl/bin/openssl pkeyutl -sign -in <input_file> -inkey "priv_key_URI" -out <output_file>
(iv)/opt/openssl/bin/openssl pkeyutl -verify -in <input_file> -sigfile <output_file> -inkey "pub_key_URI" -pubin

NOTE: Passphrase is the User PIN that was set during the OCK token configuration.
With this, we have successfully signed and verified data using OpenSSL command line with a CCA token.