grisp_pkcs11 is a generic PKCS#11 client together with the
grisp_keychain_pkcs11 adapter.
This checkout contains an end-to-end Common Test suite that exercises the public Erlang API against a real software token instead of mocks.
grisp_pkcs11 ships the grisp_keychain_pkcs11 backend for
grisp_keychain.
At runtime there are two separate responsibilities:
grisp_pkcs11starts and owns the managed PKCS#11 client processgrisp_keychaindelegates TLS certificate reads and signing togrisp_keychain_pkcs11
In practice this means:
- your system must start the
grisp_pkcs11application with a valid PKCS#11 module path grisp_keychainmust be configured with{api_module, grisp_keychain_pkcs11}- PKCS#11 token and object selection is configured under the
grisp_pkcs11application environment - generic TLS trust configuration stays under the
grisp_keychainapplication environment
Example sys.config:
[
{grisp_keychain, [
{api_module, grisp_keychain_pkcs11},
{tls_verify, verify_peer},
{tls_server_trusted_certs, <<"/etc/my_app/certificates/servers">>},
{tls_server_trusted_certs_cb, {grisp_keychain_utils, system_ca_certs}}
]},
{grisp_pkcs11, [
{token_label, "OPTEE"},
{pin, "1234"},
{key_label, "device-key"},
{cert_label, "device-cert"}
]}
].The grisp_pkcs11 application must itself be started with the PKCS#11 module
path. In this checkout, grisp_pkcs11:start_link/1 and grisp_pkcs11:child_spec/1
take that path explicitly, for example:
grisp_pkcs11:child_spec("/usr/lib/libckteec.so").The backend currently reads these PKCS#11 settings from the grisp_pkcs11
application environment:
slot_idortoken_labelto select the tokenpinorpin_fileto authenticate when requiredcert_labelandcert_idto find the client certificatekey_labelandkey_idto find the private keysign_mechanismto select the signing mechanism, currentlyecdsa
Once configured, callers use the normal grisp_keychain API. For example:
TlsOpts = grisp_keychain:tls_options("example.com"),
CertDer = grisp_keychain:read_cert(primary, der).This allows applications such as grisp_connect to use PKCS#11-backed client
identities without depending directly on the lower-level grisp_pkcs11 API.
The test suite expects these tools to be available on the host:
pkcs11-toolsofthsm2-utilopenssl
On Ubuntu, install them with:
sudo apt install opensc softhsm2 opensslThe SoftHSM PKCS#11 module shared object must also be available. On Ubuntu it is typically installed as one of:
/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so/usr/lib/aarch64-linux-gnu/softhsm/libsofthsm2.so/usr/lib/softhsm/libsofthsm2.so
If your system uses a different path, export SOFTHSM2_MODULE before running
the tests.
The test suites intentionally validate the real cross-tool workflows developers care about:
- OpenSSL-generated EC key and certificate imported with
pkcs11-tool - token-generated EC keypair created with
pkcs11-tool - object discovery through
grisp_pkcs11:list_slots/0andgrisp_pkcs11:list_objects/2 - certificate reads through
grisp_pkcs11:read_certificate/2 - digest signing through
grisp_pkcs11:sign/3 - adapter behavior through
grisp_keychain_pkcs11andgrisp_keychain - OpenSSL verification of signatures produced through Erlang
- OpenSSL verification of signatures produced directly by
pkcs11-tool - validation failures, missing PIN behavior, object lookup failures, slot-id selection, client recovery, and concurrent sign requests
The suites create a temporary SoftHSM token store under the system temp directory. They do not touch persistent system tokens.
The supported developer entrypoints are exposed through the root Makefile:
make
make build
make nif
make testmakeormake buildrunsrebar3 compilemake nifbuilds onlypriv/grisp_pkcs11_nif.somake testruns the full Common Test suite with an isolated SoftHSM setup
Run the full Common Test suite:
make testRun one suite at a time:
make test CT_ARGS="--suite=test/grisp_pkcs11_SUITE.erl"
make test CT_ARGS="--suite=test/grisp_keychain_pkcs11_SUITE.erl"make test creates an isolated temporary SOFTHSM2_CONF before Erlang starts,
which is required for SoftHSM-backed Common Test runs to behave reliably.
If you prefer to invoke rebar3 directly, you must export SOFTHSM2_CONF
yourself before starting the Erlang VM:
export SOFTHSM2_CONF="$(mktemp -d)/softhsm2.conf"
rebar3 ctYou can also override tool paths individually:
OPENSSL=/custom/bin/openssl \
PKCS11_TOOL=/custom/bin/pkcs11-tool \
SOFTHSM2_UTIL=/custom/bin/softhsm2-util \
make test- The support module lives in
test/grisp_pkcs11_test_utils.erl. - The helper module owns all external command execution and fixture creation so the suites stay declarative and easy to read.
- If a requirement is missing, suite initialization fails early with a clear error describing which executable, module path, or environment variable could not be found.