Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMS (interop) tests #49

Merged
merged 9 commits into from Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
118 changes: 94 additions & 24 deletions README.md
Expand Up @@ -6,9 +6,9 @@ oqsprovider - Open Quantum Safe provider for OpenSSL (3.0)
Purpose
-------

This repository contains code to enable quantum-safe cryptography in a
standard OpenSSL (3.0) distribution by way of implementing a single shared
library, the OQS
This repository contains code to enable quantum-safe cryptography (QSC)
in a standard OpenSSL (3.0) distribution by way of implementing a single
shared library, the OQS
[provider](https://www.openssl.org/docs/manmaster/man7/provider.html).

This repository has been derived from the [OQS-OpenSSL3 branch in
Expand All @@ -20,11 +20,12 @@ Status

Currently this provider fully enables quantum-safe cryptography for KEM
key establishment in TLS1.3 including management of such keys via the
OpenSSL (3.0) provider interface and hybrid KEM schemes. Also, OQS
signatures are available via the OpenSSL EVP interface. Key persistence is
provided via the encode/decode mechanism (still WIP for X.509).
OpenSSL (3.0) provider interface and hybrid KEM schemes. Also, QSC
signatures including CMS functionality are available via the OpenSSL
EVP interface. Key persistence is provided via the encode/decode
mechanism and X.509 data structures.

For information about the available OQS algorithms,
For information about the available QSC algorithms,
[refer to the OQS-OpenSSL documentation](https://github.com/open-quantum-safe/openssl#supported-algorithms).

Open work items are
Expand Down Expand Up @@ -90,7 +91,7 @@ Further `liboqs` build options are [documented here](https://github.com/open-qua

## Building the provider

`oqsprovider` can be build for example via the following:
`oqsprovider` can be built for example via the following:

cmake -DOPENSSL_ROOT_DIR=$(pwd)/.local -DCMAKE_PREFIX_PATH=$(pwd)/.local -S . -B _build
cmake --build _build
Expand Down Expand Up @@ -133,39 +134,95 @@ eliminates the need for specific PATH setting as showcased below.

## Checking provider version information

LD_LIBRARY_PATH=.local/lib .local/bin/openssl list -providers -verbose -provider-path _build/oqsprov -provider oqsprovider
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl list -providers -verbose -provider-path _build/oqsprov -provider oqsprovider

## Creating (classic) keys and certificates

This can be facilitated for example by running

LD_LIBRARY_PATH=.local/lib .local/bin/openssl req -x509 -new -newkey rsa -keyout rsa_CA.key -out rsa_CA.crt -nodes -subj "/CN=test CA" -days 365 -config openssl/apps/openssl.cnf
LD_LIBRARY_PATH=.local/lib .local/bin/openssl genpkey -algorithm rsa -out rsa_srv.key
LD_LIBRARY_PATH=.local/lib .local/bin/openssl req -new -newkey rsa -keyout rsa_srv.key -out rsa_srv.csr -nodes -subj "/CN=test server" -config openssl/apps/openssl.cnf
LD_LIBRARY_PATH=.local/lib .local/bin/openssl x509 -req -in rsa_srv.csr -out rsa_srv.crt -CA rsa_CA.crt -CAkey rsa_CA.key -CAcreateserial -days 365
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl req -x509 -new -newkey rsa -keyout rsa_CA.key -out rsa_CA.crt -nodes -subj "/CN=test CA" -days 365 -config openssl/apps/openssl.cnf
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl genpkey -algorithm rsa -out rsa_srv.key
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl req -new -newkey rsa -keyout rsa_srv.key -out rsa_srv.csr -nodes -subj "/CN=test server" -config openssl/apps/openssl.cnf
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl x509 -req -in rsa_srv.csr -out rsa_srv.crt -CA rsa_CA.crt -CAkey rsa_CA.key -CAcreateserial -days 365

## Setting up a (quantum-safe) test server

This can be facilitated for example by running

LD_LIBRARY_PATH=.local/lib .local/bin/openssl s_server -cert rsa_srv.crt -key rsa_srv.key -www -tls1_3 -groups kyber768:frodo640shake -provider-path _build/oqsprov -provider default -provider oqsprovider
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl s_server -cert rsa_srv.crt -key rsa_srv.key -www -tls1_3 -groups kyber768:frodo640shake -provider-path _build/oqsprov -provider default -provider oqsprovider

## Running a client to interact with (quantum-safe) KEM algorithms

This can be facilitated for example by running

LD_LIBRARY_PATH=.local/lib .local/bin/openssl s_client -groups frodo640shake -provider-path _build/oqsprov -provider default -provider oqsprovider
LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl s_client -groups frodo640shake -provider-path _build/oqsprov -provider default -provider oqsprovider

By issuing the command `GET /` the quantum-safe crypto enabled OpenSSL3
server returns details about the established connection.

Any [available KEM algorithm](https://github.com/open-quantum-safe/openssl/tree/OQS-OpenSSL_1_1_1-stable#key-exchange) can be selected by passing it in the `-groups` option.

## S/MIME message signing -- Cryptographic Message Syntax (CMS)

Also possible is the creation and verification of quantum-safe digital
signatures using [CMS](https://datatracker.ietf.org/doc/html/rfc5652).

#### Signing data

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:

LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl req -x509 -new -newkey dilithium3 -keyout qsc.key -out qsc.crt -nodes -subj "/CN=oqstest" -days 365 -config openssl/apps/openssl.cnf -provider oqsprovider -provider default

By changing the `-newkey` parameter algorithm name [any of the
supported quantum-safe or hybrid algorithms](https://github.com/open-quantum-safe/openssl/tree/OQS-OpenSSL_1_1_1-stable#authentication)
can be utilized instead of the sample algorithm `dilithium3`.

Step 2: Sign data:

As
[the CMS standard](https://datatracker.ietf.org/doc/html/rfc5652#section-5.3)
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.

LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl cms -in inputfile -sign -signer qsc.crt -inkey qsc.key -nodetach -outform pem -binary -out signedfile -md sha512 -provider-path _build/oqsprov -provider default -provider oqsprovider

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`.

#### Verifying data

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.

LD_LIBRARY_PATH=.local/lib64 .local/bin/openssl cms -verify -CAfile qsc.crt -inform pem -in signedfile -crlfeol -out outputfile -provider oqsprovider -provider default

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](scripts/oqsprovider-certgen.sh).

### Note on randomness provider

`oqsprovider` does not implement its own [DRBG](https://csrc.nist.gov/glossary/term/Deterministic_Random_Bit_Generator). Therefore by default it relies on OpenSSL to provide one. Thus, either the default or fips provider must be loaded for OQS algorithms to have access to OpenSSL-provided randomness. Check out [OpenSSL provider documentation](https://www.openssl.org/docs/manmaster/man7/provider.html) and/or [OpenSSL command line options](https://www.openssl.org/docs/manmaster/man1/openssl.html) on how to facilitate this. Or simply use the sample command lines documented in this README.
`oqsprovider` does not implement its own
[DRBG](https://csrc.nist.gov/glossary/term/Deterministic_Random_Bit_Generator).
Therefore by default it relies on OpenSSL to provide one. Thus,
either the default or fips provider must be loaded for QSC algorithms
to have access to OpenSSL-provided randomness. Check out
[OpenSSL provider documentation](https://www.openssl.org/docs/manmaster/man7/provider.html)
and/or [OpenSSL command line options](https://www.openssl.org/docs/manmaster/man1/openssl.html)
on how to facilitate this. Or simply use the sample command
lines documented in this README.

This dependency could be eliminated by building `liboqs` without OpenSSL support ([OQS_USE_OPENSSL=OFF](https://github.com/open-quantum-safe/liboqs/wiki/Customizing-liboqs#OQS_USE_OPENSSL)), which of course would be an unusual approach for an OpenSSL-OQS provider.
This dependency could be eliminated by building `liboqs` without
OpenSSL support ([OQS_USE_OPENSSL=OFF](https://github.com/open-quantum-safe/liboqs/wiki/Customizing-liboqs#OQS_USE_OPENSSL)),
which of course would be an unusual approach for an OpenSSL-OQS provider.

Team
----
Expand All @@ -176,14 +233,27 @@ Contributors to the `oqsprovider` include:
- Michael Baentsch
- Christian Paquin
- Richard Levitte
- Basil Hess

Acknowledgments
---------------

The `oqsprovider` project is supported through the [NGI Assure Fund](https://nlnet.nl/assure), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet programme](https://www.ngi.eu), under the aegis of DG Communications Networks, Content and Technology under grant agreement No 957073.

Financial support for the development of Open Quantum Safe has been provided by Amazon Web Services and the Tutte Institute for Mathematics and Computing.

We'd like to make a special acknowledgement to the companies who have dedicated programmer time to contribute source code to OQS, including Amazon Web Services, evolutionQ, Microsoft Research, Cisco Systems, and IBM Research.

Research projects which developed specific components of OQS have been supported by various research grants, including funding from the Natural Sciences and Engineering Research Council of Canada (NSERC); see [here](https://openquantumsafe.org/papers/SAC-SteMos16.pdf) and [here](https://openquantumsafe.org/papers/NISTPQC-CroPaqSte19.pdf) for funding acknowledgments.
The `oqsprovider` project is supported through the [NGI Assure Fund](https://nlnet.nl/assure),
a fund established by [NLnet](https://nlnet.nl) with financial
support from the European Commission's [Next Generation Internet programme](https://www.ngi.eu),
under the aegis of DG Communications Networks, Content and Technology
under grant agreement No 957073.

Financial support for the development of Open Quantum Safe has been provided
by Amazon Web Services and the Tutte Institute for Mathematics and Computing.

We'd like to make a special acknowledgement to the companies who have
dedicated programmer time to contribute source code to OQS, including
Amazon Web Services, evolutionQ, Microsoft Research, Cisco Systems, and IBM Research.

Research projects which developed specific components of OQS have been
supported by various research grants, including funding from the Natural
Sciences and Engineering Research Council of Canada (NSERC); see
[here](https://openquantumsafe.org/papers/SAC-SteMos16.pdf) and
[here](https://openquantumsafe.org/papers/NISTPQC-CroPaqSte19.pdf)
for funding acknowledgments.
2 changes: 1 addition & 1 deletion oqsprov/oqs_prov.h
Expand Up @@ -19,7 +19,7 @@
# include <openssl/core.h>
# include <openssl/e_os2.h>

#define OQS_PROVIDER_VERSION_STR "0.3.0"
#define OQS_PROVIDER_VERSION_STR "0.4.0-dev"

/* internal, but useful OSSL define */
# define OSSL_NELEM(x) (sizeof(x)/sizeof((x)[0]))
Expand Down
1 change: 1 addition & 0 deletions scripts/oqs-openssl-certverify.sh
Expand Up @@ -24,6 +24,7 @@ docker run -v `pwd`/tmp:/home/oqs/data -it $IMAGE sh -c "cd /home/oqs/data && op
else
# CCI doesn't permit mounting, so let's do as per https://circleci.com/docs/2.0/building-docker-images/#mounting-folders:
docker create -v /certs --name certs alpine /bin/true && \
chmod gou+rw tmp/* && \
docker cp tmp/ certs:/certs && \
docker run --volumes-from certs -it $IMAGE sh -c "cd /certs/tmp && openssl verify -CAfile $1_CA.crt $1_srv.crt" && \
docker rm /certs
Expand Down
32 changes: 32 additions & 0 deletions scripts/oqs-openssl-cmssign.sh
@@ -0,0 +1,32 @@
#!/bin/bash

# Use dockerimage to generate CMS data for alg $1

IMAGE=openquantumsafe/curl

if [ $# -ne 1 ]; then
echo "Usage: $0 <algorithmname>. Exiting."
exit 1
fi

# Assumes certgen has been run before: Quick check

if [ -f tmp/$1_CA.crt ]; then
echo "Sometext to sign" > tmp/inputfile
else
echo "File tmp/$1_CA.crt not found. Did certgen run before? Exiting."
exit -1
fi

if [[ -z "$CIRCLECI" ]]; then
docker run -v `pwd`/tmp:/home/oqs/data -it $IMAGE sh -c "cd /home/oqs/data && openssl cms -in inputfile -sign -signer $1_srv.crt -inkey $1_srv.key -nodetach -outform pem -binary -out signedfile.cms && openssl cms -verify -CAfile $1_CA.crt -inform pem -in signedfile.cms -crlfeol -out signeddatafile "
else
# CCI doesn't permit mounting, so let's do as per https://circleci.com/docs/2.0/building-docker-images/#mounting-folders:
docker create -v /certs --name certs alpine /bin/true && \
touch tmp/signedfile.cms && touch tmp/signeddatafile && chmod gou+rw tmp/* && \
docker cp tmp/ certs:/certs && \
docker run --volumes-from certs --rm --name oqsossl -it $IMAGE sh -c "cd /certs/tmp && openssl cms -in inputfile -sign -signer $1_srv.crt -inkey $1_srv.key -nodetach -outform pem -binary -out signedfile.cms && openssl cms -verify -CAfile $1_CA.crt -inform pem -in signedfile.cms -crlfeol -out signeddatafile " && \
docker cp certs:/certs/tmp . && \
docker rm certs
fi

33 changes: 33 additions & 0 deletions scripts/oqs-openssl-cmsverify.sh
@@ -0,0 +1,33 @@
#!/bin/bash

#set -x

# Use dockerimage to verify certs for alg $1

IMAGE=openquantumsafe/curl

if [ $# -ne 1 ]; then
echo "Usage: $0 <algorithmname>. Exiting."
exit 1
fi

if [ ! -d tmp ]; then
echo "Test folder tmp not existing. Exiting."
exit 1
fi

if [ ! -f tmp/$1_srv.crt ]; then
echo "Cert to test not present. Exiting."
exit 1
fi

if [[ -z "$CIRCLECI" ]]; then
docker run -v `pwd`/tmp:/home/oqs/data -it $IMAGE sh -c "cd /home/oqs/data && openssl cms -verify -CAfile $1_CA.crt -inform pem -in signedfile.cms -crlfeol -out signeddatafile && diff signeddatafile inputfile"
else
# CCI doesn't permit mounting, so let's do as per https://circleci.com/docs/2.0/building-docker-images/#mounting-folders:
docker create -v /certs --name certs alpine /bin/true && \
chmod gou+rw tmp/* && \
docker cp tmp/ certs:/certs && \
docker run --volumes-from certs -it $IMAGE sh -c "cd /certs/tmp && openssl cms -verify -CAfile $1_CA.crt -inform pem -in signedfile.cms -crlfeol -out signeddatafile && diff signeddatafile inputfile" && \
docker rm certs
fi
33 changes: 33 additions & 0 deletions scripts/oqsprovider-cmssign.sh
@@ -0,0 +1,33 @@
#!/bin/bash

# Use newly built oqsprovider to generate CMS signed files for alg $1
# Assumes .local to contain openssl(3) and oqsprovider to be in _build folder
# Assumed oqsprovider-certgen.sh to have run before for same algorithm

# uncomment to see what's happening:
# set -x

if [ $# -ne 1 ]; then
echo "Usage: $0 <algorithmname>. Exiting."
exit 1
fi

# Assumes certgen has been run before: Quick check

if [ -f tmp/$1_CA.crt ]; then
echo "Sometext to sign" > tmp/inputfile
else
echo "File tmp/$1_CA.crt not found. Did certgen run before? Exiting."
exit -1
fi

export OPENSSL_MODULES=_build/oqsprov
export LD_LIBRARY_PATH=.local/lib64
.local/bin/openssl x509 -provider oqsprovider -provider default -in tmp/$1_srv.crt -pubkey -noout > tmp/$1_srv.pubkey && .local/bin/openssl cms -in tmp/inputfile -sign -signer tmp/$1_srv.crt -inkey tmp/$1_srv.key -nodetach -outform pem -binary -out tmp/signedfile.cms -md sha512 -provider oqsprovider -provider default

if [ $? -eq 0 ]; then
# run internal test:
.local/bin/openssl cms -verify -CAfile tmp/$1_CA.crt -inform pem -in tmp/signedfile.cms -crlfeol -out tmp/signeddatafile -provider oqsprovider -provider default && diff tmp/signeddatafile tmp/inputfile
else
exit -1
fi
27 changes: 27 additions & 0 deletions scripts/oqsprovider-cmsverify.sh
@@ -0,0 +1,27 @@
#!/bin/bash

# Use newly built oqsprovider to generate CMS signed files for alg $1
# Assumes .local to contain openssl(3) and oqsprovider to be in _build folder
# Assumed oqsprovider-certgen.sh to have run before for same algorithm

# uncomment to see what's happening:
# set -x

if [ $# -ne 1 ]; then
echo "Usage: $0 <algorithmname>. Exiting."
exit 1
fi

# Assumes certgen has been run before: Quick check

if [ -f tmp/signedfile.cms ]; then
export OPENSSL_MODULES=_build/oqsprov
export LD_LIBRARY_PATH=.local/lib64
.local/bin/openssl cms -verify -CAfile tmp/$1_CA.crt -inform pem -in tmp/signedfile.cms -crlfeol -out tmp/signeddatafile -provider oqsprovider -provider default
diff tmp/signeddatafile tmp/inputfile
#rm tmp/signeddatafile tmp/signedfile.cms
else
echo "File tmp/signedfile.cms not found. Did CMS sign run before? Exiting."
exit -1
fi

10 changes: 8 additions & 2 deletions scripts/runtests.sh
@@ -1,13 +1,15 @@
#!/bin/sh

provider2openssl() {
echo
echo "Testing oqsprovider->oqs-openssl interop for $1:"
./scripts/oqsprovider-certgen.sh $1 && ./scripts/oqs-openssl-certverify.sh $1
./scripts/oqsprovider-certgen.sh $1 && ./scripts/oqsprovider-cmssign.sh $1 && ./scripts/oqs-openssl-certverify.sh $1 && ./scripts/oqs-openssl-cmsverify.sh $1
}

openssl2provider() {
echo
echo "Testing oqs-openssl->oqsprovider interop for $1:"
./scripts/oqs-openssl-certgen.sh $1 && ./scripts/oqsprovider-certverify.sh $1
./scripts/oqs-openssl-certgen.sh $1 && ./scripts/oqs-openssl-cmssign.sh $1 && ./scripts/oqsprovider-certverify.sh $1 && ./scripts/oqsprovider-cmsverify.sh $1
}

interop() {
Expand All @@ -21,6 +23,10 @@ interop() {
provider2openssl $1 && openssl2provider $1
fi

if [ $? -ne 0 ]; then
echo "Test for $1 failed. Terminating testing."
exit -1
fi
}

# Output version:
Expand Down