Skip to main content

OpenSSL CLI

Introduction

This tutorial provides an overview of how to use the OpenSSL command line interface (CLI) with a Primus HSM. For a comprehensive guide on all available commands and options, please refer to the OpenSSL man page.

info

Generally, we recommend using native PKCS#11 tools like pkcs11-tool for management functions such as generating, importing, and deleting objects on the HSM. These tools has fewer levels of indirection because they use the PKCS#11 APIs directly.

In particular, OpenSSL may not support all features, or may show errors despite the operation having succeeded.

See this tutorial for how to use the native PKCS#11 tools.

Referencing objects

PKCS#11 objects are referenced via the PKCS#11 URI scheme defined by RFC 7512.

Wherever a key is used as an input argument, its PKCS#11 URI can be entered in place of a file name. When generating a key, the URI can be passed as a pkeyopt (e.g. -pkeyopt "pkcs11_uri:pkcs11:type=private?object=SomeLabel").

In OpenSSL 3.x the "Property" mechanism can be used to limit the selection of different algorithm implementations. The propquery parameter is available for many of the commands that are accessible through the CLI. When setting -propquery "provider=pkcs11" only algorithms that are offered by the OpenSSL PKCS#11 provider will be used.

Finally, recall that the "token label" (in PKCS#11 terms) refers to the partition name on a Primus HSM.

warning

The pkcs11_uri: prefix is only needed for -pkeyopt. In other arguments, such as -inkey, you need to specify the PKCS#11 URI without this prefix.

Prerequisites

This tutorial assumes that you have fully configured the entire stack of OpenSSL, a provider or an engine, and the PKCS#11 libraries.

Use the following command to check that the provider/engine (depending on which setup you chose) is loaded by OpenSSL:

openssl list -providers
openssl list -engines
warning

Note that the provider-based setup requires OpenSSL 3.x, while the engine-based setup works with both OpenSSL 1.x and 3.x. Depending on which setup you chose, the commands below will differ.

Make sure to use the correct command for your setup!

Common environment variables

All command samples on this page assume that you have defined the following environment variables:

export P11_TOKEN=<YOUR_HSM_PARTITION_NAME>
export P11_PIN=<YOUR_PKCS11_PASSWORD>
export P11_LABEL=<YOUR_PKCS11_KEY_NAME>

Generate a key pair

info

The key generation commands below are only compatible with OpenSSL 3.x using a provider-based setup. If you are using OpenSSL 1.x or OpenSSL 3.x with an engine-based setup you can generate keys with pkcs11-tool. In fact, we recommend to use pkcs11-tool for OpenSSL 3.x, too, because it has better compatibility.

The following table lists popular supported algorithms and algorithm options:

ALGORITHMALGORITHM_OPT
rsarsa_keygen_bits:2048
rsarsa_keygen_bits:3072
rsarsa_keygen_bits:4096
ECec_paramgen_curve:prime256v1
ECec_paramgen_curve:secp384r1
ECec_paramgen_curve:secp521r1
Ed25519-
Ed448-
ML-DSA-44-
ML-DSA-65-
ML-DSA-87-

Generate the key pair:

export ALGORITHM=<PREFERRED_ALGO>
export ALGORITHM_OPT=<PREFERRED_ALGO_OPTION>
openssl genpkey -propquery "provider=pkcs11" \
-algorithm "${ALGORITHM}" \
${ALGORITHM_OPT:+-pkeyopt} ${ALGORITHM_OPT} \
-pkeyopt "pkcs11_uri:pkcs11:token=${P11_TOKEN};object=${P11_LABEL}?pin-value=${P11_PIN}"

Export a public key

For the provider-based setup:

openssl pkey -propquery "provider=pkcs11" \
-pubin -in "pkcs11:token=${P11_TOKEN};object=${P11_LABEL}?pin-value=${P11_PIN}" \
-outform PEM -out "${P11_LABEL}.pub.pem"

For the engine-based setup:

openssl pkey -engine pkcs11 -inform engine \
-in "pkcs11:type=public;object=${P11_LABEL}" -pubin

Sign data

For the provider-based setup:

openssl pkeyutl -propquery "provider=pkcs11" -sign \
-inkey "pkcs11:token=${P11_TOKEN};object=${P11_LABEL}?pin-value=${P11_PIN}" \
-rawin -in data.txt -out data.txt.sig

For Ed25519, pass the following additional arguments to include a context-string (Ed448ctx currently does not work):

-pkeyopt instance:Ed25519ctx -pkeyopt context-string:hello-world

For Ed25519/Ed448, pass the following additional arguments to use the pre-hashed variant:

-pkeyopt instance:Ed25519ph
# or
-pkeyopt instance:Ed448ph

For verification, pass the same additional arguments.

Verify signature

For the provider-based setup:

openssl pkeyutl -verify \
-pubin -inkey "${P11_LABEL}.pub.pem" \
-rawin -in data.txt -sigfile data.txt.sig

This example assumes that you have exported the public key to a local file, as shown above.

Create a Certificate Signing Request (CSR)

For the provider-based setup:

openssl req -propquery "provider=pkcs11" \
-new -key "pkcs11:token=${P11_TOKEN};object=${P11_LABEL}?pin-value=${P11_PIN}" \
-out "${P11_LABEL}.csr.pem"

For the engine-based setup:

openssl req -engine pkcs11 -keyform engine \
-new -key "pkcs11:object=${P11_LABEL}" \
-out "${P11_LABEL}.csr.pem"

Create a self-signed certificate

To create a self-signed, use the same command as for creating a CSR, but additionally pass the -x509 option:

openssl req -propquery "provider=pkcs11" \
-new -key "pkcs11:token=${P11_TOKEN};object=${P11_LABEL}?pin-value=${P11_PIN}" \
-x509 -out "${P11_LABEL}.crt.pem"
note

The certificate is not stored on the HSM. The certificate needs to be written to the token explicitly. See the PKCS#11 docs for how to import a certificate.

Further reading

Get started withCloudHSM for free.
Other questions?Ask Sales.
Feedback
Need help?