Lorica provides tools for operating a certification authority (CA) that leverages PKCS #11 cryptographic tokens.
By design, Lorica does not get hold of the private key. Instead, it asks another device, usually a hardware security module (HSM), to perform the cryptographic functions on its behalf.
Such devices, commonly known as cryptographic tokens, are purpose-built to generate cryptographic keys and sign information without revealing the private key. This greatly reduces the risk of key compromise, one of the main risks certification authorities defend against.
Lorica interacts with cryptographic tokens using the Cryptoki API, as specified by the PKCS #11 standard.
SoftHSM2 is a software implementation of a generic cryptographic token with a PKCS #11 interface.
SoftHSM2 is required for running the test suite. The user running the
test suite should have access to softhsm2-util
command and the PKCS#11
module should be available at /usr/lib/softhsm/libsofthsm2.so
.
In this tutorial, we will use the lorica
command-line tool with a
SoftHSM2 token to deploy a two-tier PKI.
Lorica loads PKCS #11 token configurations from environment variables,
you can also use a .env
file like this:
LORICA_TOKEN_MODULE="/usr/lib/softhsm/libsofthsm2.so"
LORICA_TOKEN_LABEL=lorica_demo
LORICA_TOKEN_PIN=123456
The token must be initialized before use. For SoftHSM2, you can do it by using this command:
$ softhsm2-util --init-token --free --label lorica_demo --pin 123456 --so-pin lorica
You can do a quick smoke test with the lorica info
command:
$ lorica info
Token label: lorica_demo
Manufacturer: SoftHSM project
Token model: SoftHSM v2
Serial number: 4788d9b901eef752
First we need to prepare a configuration file in JSON format, like this:
{
"CN": "Pied Piper Root CA",
"name": {
"OU": "Certification Authority",
"O": "Pied Piper",
"L": "Silicon Valley",
"ST": "CA",
"C": "US"
},
"key": {
"algo": "rsa",
"size": 4096
},
"self_sign": true,
"expiry": "87600h",
"ca_constraint": {
"is_ca": true
}
}
Then we use the lorica init
command to set up the Root CA:
$ lorica init root_ca.json -f root.ca
This will create a new file, root.ca
, which keeps the internal state.
Just specify this file when running a command and Lorica will know which
CA you are working with. For example, to view the certificate of Root
CA:
$ lorica cert -f root.ca | openssl x509 -noout -text
Similarly, prepare a configuration for the Subordinate CA. Note that we
have self_sign
set to false:
{
"CN": "Pied Piper Subordinate CA",
"name": {
"OU": "Certification Authority",
"O": "Pied Piper",
"L": "Silicon Valley",
"ST": "CA",
"C": "US"
},
"key": {
"algo": "rsa",
"size": 2048
},
"self_sign": false,
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "8760h",
"ca_constraint": {
"is_ca": false
}
}
Use the same lorica init
command to set up the Subordinate CA. Only
this time, we need to export the CSR.
$ lorica init sub_ca.json -f sub.ca --export-csr sub_ca.csr
After that, ask the Root CA to sign the CSR of the Subordinate CA and import the newly-issued certificate to the Subordinate CA:
$ lorica issue -f root.ca sub_ca.csr --export-cert sub_ca.crt
$ lorica cert -f sub.ca --import sub_ca.crt
The Subordinate CA is now fully operational.
Create a CSR for the end-entity:
$ openssl req -nodes -newkey rsa:2048 -sha256 \
-subj /CN=piedpiper.example.com \
-keyout piedpiper.example.com.key \
-out piedpiper.example.com.csr
Ask Subordinate CA to sign the CSR and export the issued certificate:
$ lorica issue -f sub.ca piedpiper.example.com.csr --export-cert piedpiper.example.com.crt
To revoke a certificate, pass its serial number to the lorica revoke
command:
$ lorica revoke -f sub.ca 154650704943387378214337212672624373342364461517
After that, update the certificate revocation list:
$ lorica crl -f sub.ca sub_ca.crl
Inpsect the CRL to confirm the certificate is now being revoked:
$ openssl crl -inform DER -text -noout -in sub_ca.crl