This file documents information required to properly utilize oqsprovider
after installation on a machine running openssl
v3.
Beware that oqsprovider
will not work on machines where an OpenSSL
version below "3.0.0" is (the default) installed.
An openssl
version >= 3.0.0 is available and set in the "PATH" environment
variable such as that the command openssl version
yields a result documenting
this, e.g., as follows:
OpenSSL 3.2.0-dev (Library: OpenSSL 3.2.0-dev )
If one does not have an OpenSSL version installed in a suitable version, care
is advised installing such version such as not to damage a pre-installed/system-wide
openssl
installation.
In order to experiment with a local openssl
version, we have made available
a shell script creating a local, non-system wide installed
openssl
binary. By default, the current "master" branch is built by this script
but it can be configured to build any release/tag by setting the OPENSSL_BRANCH
environment variable.
Every OpenSSL provider needs to be activated for use. There are three main ways for this:
Most openssl
commands permit passing the option -provider
: The name after
this command is that of the provider to be activated.
As an example: openssl list -signature-algorithms -provider oqsprovider
outputs all quantum safe signature algorithms made available for openssl
use.
All openssl
commands accepting -provider
also permit passing -provider-path
as a possibility to reference the location in the local filesystem where the
provider binary is located. This is of particular use if the provider did not
(yet) get installed in the system location, which typically is in lib/ossl-modules
in the main openssl
installation tree.
If activation of oqsprovider
should be hard-coded in a C program, use of the
standard OSSL_PROVIDER_load
API may be considered, e.g., as such:
OSSL_PROVIDER_load(OSSL_LIB_CTX_new(), "oqsprovider");
The provider (binary) search path may be set via the OSSL_PROVIDER_set_default_search_path API.
If all code should be "baked" into one executable, be sure to statically build
oqsprovider
using the OQS_PROVIDER_BUILD_STATIC
configuration option and use
the integration code documented.
As an alternative to passing command line parameters or hard-coding C code, providers
can be activated for general use by adding instructions to the openssl.cnf
file.
In the case of oqs-provider
add these lines to achieve this:
[provider_sect]
default = default_sect
oqsprovider = oqsprovider_sect
[oqsprovider_sect]
activate = 1
Next to the "activate" keyword, openssl
also recognizes the "module" keyword
which mirrors the functionality of -provider-path
documented above: This way,
a non-standard location for the oqsprovider
shared library (.SO/.DYLIB/.DLL)
can be registered for testing.
If this configuration variable is not set, the global environment variable
"OPENSSL_MODULES" must point to a directory where the oqsprovider
binary
is to be found.
If the oqsprovider
binary cannot be found, it simply (and silently) will
not be available for use.
The system-wide openssl.cnf
file is typically located at (operating system dependent):
- /etc/ssl/ (UNIX/Linux)
- /opt/homebrew/etc/openssl@3/ (MacOS Homebrew on Apple Silicon)
- /usr/local/etc/openssl@3/ (MacOS Homebrew on Intel Silicon)
- C:\Program Files\Common Files\SSL\ (Windows)
Adding oqsprovider
to this file will enable its seamless operation alongside other
openssl
providers. If successfully done, running, e.g., openssl list -providers
should output something along these lines (version IDs variable of course):
providers:
default
name: OpenSSL Default Provider
version: 3.1.1
status: active
oqsprovider
name: OpenSSL OQS Provider
version: 0.5.0
status: active
If this is the case, all openssl
commands can be used as usual, extended
by the option to use quantum safe cryptographic algorithms in addition/instead
of classical crypto algorithms.
This configuration is the one used in all examples below.
Note: Be sure to always activate either the "default" or "fips" provider as these
deliver functionality also needed by oqsprovider
(e.g., for hashing or high
quality random data during key generation).
For activating specific KEMs, three options exist:
All commands allowing pre-selecting KEMs for use permit this via the standard OpenSSL -groups command line option. See example commands below.
If activation of specific KEM groups should be hard-coded into a C program, use the standard OpenSSL SSL_set1_groups_list API, e.g., as such:
SSL_set1_groups_list(ssl, "kyber768:kyber1024");
The set of acceptable KEM groups can also be set in the openssl.cnf
file
as per this example:
[openssl_init]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
Groups = kyber768:kyber1024
Be sure to separate permissible KEM names by colon if specifying several.
The following section provides example commands for certain standard OpenSSL operations.
openssl list -providers -verbose
openssl list -signature-algorithms -provider oqsprovider
openssl list -kem-algorithms -provider oqsprovider
This can be facilitated for example by using the usual openssl
commands:
openssl req -x509 -new -newkey dilithium3 -keyout dilithium3_CA.key -out dilithium3_CA.crt -nodes -subj "/CN=test CA" -days 365 -config openssl/apps/openssl.cnf
openssl genpkey -algorithm dilithium3 -out dilithium3_srv.key
openssl req -new -newkey dilithium3 -keyout dilithium3_srv.key -out dilithium3_srv.csr -nodes -subj "/CN=test server" -config openssl/apps/openssl.cnf
openssl x509 -req -in dilithium3_srv.csr -out dilithium3_srv.crt -CA dilithium3_CA.crt -CAkey dilithium3_CA.key -CAcreateserial -days 365
These examples create QSC dilithium3 keys but the very same commands can be used to create QSC certificates replacing the key type "dilithium3" with any of the QSC signature algorithms supported. Of course, also any classic signature algorithm like "rsa" may be used.
Using keys and certificates as created above, a simple server utilizing a quantum-safe (QSC) KEM algorithm and certicate can be set up for example by running
openssl s_server -cert dilithium3_srv.crt -key dilithium3_srv.key -www -tls1_3 -groups kyber768:frodo640shake
Instead of "dilithium3" any QSC signature algorithm supported may be used as well as any classic crypto signature algorithm. Instead of "kyber768:frodo640shake" any combination of QSC KEM algorithm(s) and classic crypto KEM algorithm(s) may be specified.
This can be facilitated for example by running
openssl s_client -groups frodo640shake
By issuing the command GET /
the quantum-safe crypto enabled OpenSSL3
server returns details about the established connection.
Any available quantum-safe KEM algorithm can be selected by passing it in the -groups
option.
Also possible is the creation and verification of quantum-safe digital signatures using CMS.
For creating signed data, two steps are required: One is the creation of a certificate using a QSC algorithm; the second is the use of this certificate (and its signature algorithm) to create the signed data:
Step 1: Create quantum-safe key pair and self-signed certificate:
openssl req -x509 -new -newkey dilithium3 -keyout qsc.key -out qsc.crt -nodes -subj "/CN=oqstest" -days 365 -config openssl/apps/openssl.cnf
By changing the -newkey
parameter algorithm name any of the
supported quantum-safe or hybrid algorithms
can be utilized instead of the sample algorithm dilithium3
.
Step 2: Sign data:
As
the CMS standard
requires the presence of a digest algorithm, while quantum-safe crypto
does not, in difference to the QSC certificate creation command above,
passing a message digest algorithm via the -md
parameter is mandatory.
openssl cms -in inputfile -sign -signer qsc.crt -inkey qsc.key -nodetach -outform pem -binary -out signedfile -md sha512
Data to be signed is to be contained in the file named inputfile
. The
resultant CMS output is contained in file signedfile
. The QSC algorithm
used is the same signature algorithm utilized for signing the certificate
qsc.crt
.
Continuing the example above, the following command verifies the CMS file
signedfile
and outputs the outputfile
. Its contents should be identical
to the original data in inputfile
above.
openssl cms -verify -CAfile qsc.crt -inform pem -in signedfile -crlfeol -out outputfile
Note that it is also possible to build proper QSC certificate chains using the standard OpenSSL calls. For sample code see scripts/oqsprovider-certgen.sh.
Also tested to operate OK is the openssl dgst command. Sample invocations building on the keys and certificate files in the examples above:
openssl dgst -sign qsc.key -out dgstsignfile inputfile
openssl dgst -signature dgstsignfile -verify qsc.pubkey inputfile
The public key can be extracted from the certificate using standard openssl command:
openssl x509 -in qsc.crt -pubkey -noout > qsc.pubkey
The dgst
command is not tested for interoperability with oqs-openssl111.
Note on KEM Decapsulation API:
The OpenSSL EVP_PKEY_decapsulate
API specifies an explicit return value for failure. For security reasons, most KEM algorithms available from liboqs do not return an error code if decapsulation failed. Successful decapsulation can instead be implicitly verified by comparing the original and the decapsulated message.
OpenSSL 3 comes with the OSSL_PARAM
API.
Through these [OSSL_PARAM
] structures, oqs-provider can expose some useful information
about a specific object.
Using the EVP_PKEY_get_params
API, the following custom parameters are gettable:
OQS_HYBRID_PKEY_PARAM_CLASSICAL_PUB_KEY
: points to the public key of the classical part of an hybrid key.OQS_HYBRID_PKEY_PARAM_CLASSICAL_PRIV_KEY
: points to the private key of the classical part of an hybrid key.OQS_HYBRID_PKEY_PARAM_PQ_PUB_KEY
: points to the public key of the quantum-resistant part of an hybrid key.OQS_HYBRID_PKEY_PARAM_PQ_PRIV_KEY
: points to the private key of the quantum-resistant part of an hybrid key.
In case of non hybrid keys, these parameters return NULL
.
See the corresponding test for an example of
how to use [EVP_PKEY_get_params
] with custom oqs-provider parameters.