Key Management via PKCS#11
This tutorial shows how to do basic key management (listing keys, generating keys, creating certificates)
with PKCS#11 command line tools, namely pkcs11-tool
, p11tool
, and certtool
.
Installation
Make sure that the Primus PKCS#11 Provider is installed in /usr/local/primus
and is fully configured as per the docs.
The pkcs11-tool
comes from the OpenSC project; p11tool
and certtool
come from GnuTLS.
To get these tools, install the following packages:
CLI tool | Debian package | RHEL package |
---|---|---|
pkcs11-tool | opensc-pkcs11 | opensc |
p11tool , certtool | gnutls-bin | gnutls-utils |
Environment
Define the variables to be used later:
export P11_PIN=<YOUR_PKCS11_PASSWORD>
export P11_TOKEN=<YOUR_HSM_PARTITION_NAME>
export P11_LABEL=<YOUR_PKCS11_KEY_LABEL>
export P11_LIB=/usr/local/primus/lib/libprimusP11.so
The P11_PIN
is the PKCS#11 Password that you have configured.
If you omit the --pin
(pkcs11-tool
) or the --set-pin
(p11tool) option you will be prompted to enter the PIN interactively.
On Windows, the module path would be C:\Program Files\Securosys\Primus P11\primusP11.dll
.
pkcs11-tool
(from OpenSC)
The pkcs11-tool
test function (--test
) is not recommended and may fail due to incompatibilities.
List objects
pkcs11-tool --module ${P11_LIB} \
--login --pin ${P11_PIN} \
--list-objects --type privkey
Available types are cert, privkey, pubkey, secrkey, data
.
Generate a key pair
pkcs11-tool --module ${P11_LIB} \
--login --pin ${P11_PIN} \
--keypairgen --key-type RSA:2048 \
--slot 0 --label ${P11_LABEL} --sensitive
Other available key types include RSA:4096
, EC:secp256r1
, and EC:secp384r1
.
To show all available elliptic curves, provide an invalid curve:
pkcs11-tool --module ${P11_LIB} --keypairgen --key-type EC:
Using slot 0 with a present token (0x0)
EC key parameters may be specified by their canonic name or object identifier. Possible values are:
secp192r1 (1.2.840.10045.3.1.1)
prime192v1 (1.2.840.10045.3.1.1)
prime192v2 (1.2.840.10045.3.1.2)
prime192v3 (1.2.840.10045.3.1.3)
<more curves>
You can also find the list of curves on GitHub.
However, note that the upstream source code may have newer curves that are not yet included in the version
of pkcs11-tool
that you installed from your distribution's repository.
Generate a symmetric key
pkcs11-tool --module ${P11_LIB} \
--login --pin ${P11_PIN} \
--keygen --key-type AES:32 \
--slot 0 --label ${P11_LABEL}
Export a public key
pkcs11-tool --module ${P11_LIB} \
--login --pin ${P11_PIN} \
--read-object --type pubkey \
--label ${P11_LABEL} \
--output-file ${P11_LABEL}.pub.der \
--slot 0
To view the ASN1:
openssl asn1parse -in ${P11_LABEL}.pub.der -inform DER -i
dumpasn1 ${P11_LABEL}.pub.der
To convert to PEM (with OpenSSL 3.x):
openssl rsa -in ${P11_LABEL}.pub.der -pubin -inform DER -outform PEM -out ${P11_LABEL}.pub.pem
Use openssl ec
with the same options for an EC key.
Import a certificate
See below for how to use certtool
to create a certificate.
pkcs11-tool --module ${P11_LIB} \
--login --pin ${P11_PIN} \
--write-object ${P11_LABEL}.crt.pem --type cert \
--slot 0 --label ${P11_LABEL}
Delete an object
pkcs11-tool --module ${P11_LIB} \
--login --pin ${P11_PIN} \
--delete-object --type pubkey \
--label ${P11_LABEL}
p11tool
(from GnuTLS)
p11tool
is aware of p11-kit
.
If you configure p11-kit you don't need to specify the --provider
option every time.
(Instead, you may need to specify the token URL.)
List tokens
Every HSM partition will show as a token.
p11tool --provider ${P11_LIB} --list-tokens
List objects
p11tool --provider ${P11_LIB} \
--login --set-pin ${P11_PIN} \
--list-all
"pkcs11:token=${P11_TOKEN}"
Generate a key pair
Generate an RSA key:
p11tool --provider ${P11_LIB} \
--login --set-pin ${P11_PIN} \
--generate-privkey RSA --bits 2048 \
--label ${P11_LABEL} \
"pkcs11:token=${P11_TOKEN}"
Generate an EC key:
p11tool --provider ${P11_LIB} \
--login --set-pin ${P11_PIN} \
--generate-privkey ECC --curve secp256r1 \
--label ${P11_LABEL} \
"pkcs11:token=${P11_TOKEN}"
See man p11tool
for the list of available parameters.
Export a public key
p11tool --provider ${P11_LIB} \
--login --set-pin ${P11_PIN} \
--export-pubkey --outfile ${P11_LABEL}.pub.pem \
"pkcs11:token=${P11_TOKEN};object=${P11_LABEL}"
Import a certificate
See below for how to use certtool
to create a certificate.
p11tool --provider ${P11_LIB} \
--login --set-pin ${P11_PIN} \
--write --load-certificate ${P11_LABEL}.crt.pem \
--label ${P11_LABEL} \
"pkcs11:token=${P11_TOKEN}"
Delete an object
p11tool --provider ${P11_LIB} \
--login --set-pin ${P11_PIN} \
--delete \
"pkcs11:token=${P11_TOKEN};object=${P11_LABEL}"
You will be shown the objects to be deleted and will be prompted to interactively confirm their deletion.
certtool
(from GnuTLS)
Usually, certificates cannot be directly created on the HSM via PKCS#11 commands. Instead, you have to use helper tools to create a Certificate Signing Request (CSR). The CSR is then signed by a private key on the HSM to create a certificate. On the PKCS#11-level, this is just signing an opaque bitstring; thus you need helper tools that handle building the X.509 structures. Finally, you can import the certificate into the HSM (if desired).
In this example, we use certtool
from the GnuTLS utils to create certificates.
We assume that you have created two key pairs on the HSM, with labels root
and leaf
.
We will create a self-signed certificate for the root
key pair,
and then create a certificate for the leaf
key pair signed by root.
Finally, we will verify the certificate chain.
Like p11tool
, certtool
is aware of p11-kit
.
Therefore, you can drop the --provider
option if you have p11-kit configured.
Create a self-signed certificate
certtool --provider ${P11_LIB} \
--password ${P11_PIN} \
--generate-self-signed \
--load-privkey "pkcs11:token=${P11_TOKEN};type=private;object=root" \
--outfile root.crt.pem
Create a certificate signed by a CA
Create a CSR:
certtool --provider ${P11_LIB} \
--password ${P11_PIN} \
--generate-request \
--load-privkey "pkcs11:token=${P11_TOKEN};type=private;object=leaf" \
--outfile leaf.csr.pem
Create a certificate from the CSR:
certtool --provider ${P11_LIB} \
--password ${P11_PIN} \
--generate-certificate \
--load-request leaf.csr.pem \
--load-ca-certificate root.crt.pem \
--load-ca-privkey "pkcs11:token=${P11_TOKEN};type=private;object=root" \
--outfile leaf.crt.pem
View certificate info
certtool --certificate-info --infile root.crt.pem
Verify a certificate
certtool \
--verify \
--load-ca-certificate root.crt.pem \
--infile leaf.crt.pem