Apache httpd with hybrid ML-KEM Post-Quantum Cryptography 07 dec 2024 | Last updated: 09 dec 2024 00:00

The first Post-Quantum Cryptography algorithms have been selected by NIST. Let's see if we can run an Apache httpd server on FreeBSD 14.2 using OpenSSL, liboqs, and oqs-provider.

Apache httpd with hybrid ML-KEM Post-Quantum Cryptography

There's been recent developments in Post-Quantum Cryptography that caught my attention.

  1. 2024-08-13 NIST published 3 PQC algorythm standards.
  2. 2024-11-12: NIST published an initial public draft "Transition to Post-Quantum Cryptography Standards".
  3. 2024-12-03: AIVD publishes "Het PQC-migratie handboek" (Dutch).

So I thought it's time to see if we can run a webserver that uses PQC algorithms.

With any luck (if your browser is up-to-date), this page was served using hybrid Post-Quantum Cryptography algorithm X25519MLKEM768!

What do we need?

Shopping list

  1. The Open Quantum Security liboqs library with the Kyber ML-KEM algorithms.
  2. The OpenSSL oqs-provider engine.
  3. An Apache httpd server using OpenSSL (that's "normal" for most installs).
  4. Configuration for Apache httpd to enable the OpenSSL provider and ML-KEM algorithms.

Luckily, the liboqs library has already been ported to FreeBSD but the oqs-provider does not exist yet.

Porting the OpenSSL OQS Provider

You can skip this chapter if all you want is Apache with ML-KEM!

You need a recent OpenSSL version, the one in FreeBSD base should work but has known issues. Best to use the latest release, at time of writing that was OpenSSL 3.4.0 (non-LTS). Since I use my own LibreBSD environment, I have to switch the default OpenSSL library anyway as LibreSSL does not support MK-KEM (yet?).

# /etc/make.conf
DEFAULT_VERSIONS+=   ssl=openssl34

Then we build and install liboqs. As you can see it uses the OpenSSL library from ports and ignores OpenSSL 3.0 or 1.1.1 from base.

cd /usr/ports/security/libqs
make configure
...
-- Found OpenSSL: /usr/local/lib/libcrypto.so (found suitable version "3.4.0", minimum required is "1.1.1")
...
make reinstall

Now we're ready to port OpenSSL OQS-provider. This is a pretty basic Makefile for a port, and even the tests are OK.

```sh
Test project /wrkdir/usr/ports/security/openssl_oqs-provider/work/.build
    Start 1: oqs_signatures
    Start 2: oqs_kems
    Start 3: oqs_groups
    Start 4: oqs_tlssig
    Start 5: oqs_endecode
    Start 6: oqs_evp_pkey_params
1/6 Test #2: oqs_kems .........................   Passed    0.35 sec
2/6 Test #3: oqs_groups .......................   Passed    0.49 sec
3/6 Test #6: oqs_evp_pkey_params ..............   Passed    1.68 sec
4/6 Test #4: oqs_tlssig .......................   Passed    6.65 sec
5/6 Test #1: oqs_signatures ...................   Passed    8.37 sec
6/6 Test #5: oqs_endecode .....................   Passed   11.40 sec
                                                                                                                                                                                      100% tests passed, 0 tests failed out of 6

Total Test time (real) =  11.41 sec

This was all in my porting jail. I've created packages so we can install and use this in my Apache httpd jail.

Enabling ML-KEM support in Apache httpd

This should work on FreeBSD 14.x which has OpenSSL 3.0 in base, but there are known problems, so best build an environment with OpenSSL from ports. Modify your make.conf file to set the OpenSSL version. I've tried OpenSSL 3.3 and 3.4.

# /etc/make.conf
DEFAULT_VERSIONS+=   ssl=openssl34

Continue with (re-)building security/openssl, security/liboqs, security/openssl_oqs-provider, devel/apr1 and www/httpd. Create packages for deployment.

Tip: Use a poudriere "set" that uses OpenSSL 3.4 from ports.

cd /usr/ports/security/openssl34
make clean package reinstall && \
cd /usr/ports/security/liboqs && \
make clean package reinstall && \
cd /usr/ports/security/openssl_oqs-provider && \
make clean package reinstall && \
cd /usr/ports/devel/apr1 && \
make clean package reinstall && \
cd /usr/ports/www/apache24 && \
make clean package

Make sure you have all fresh packages in /usr/ports/packages/All.

To be able to verify that we have a working OpenSSL library with OQS-provider, you could use curl.

Configure OpenSSL

To enable OQS-provider, we need to modify the openssl.cnf file. On FreeBSD this is /usr/local/openssl/openssl.cnf. In a stock OpenSSL configuration we need to modify the provider_sect section. You should find it by following the references starting with openssl_conf.

# Use this in order to automatically load providers.
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
oqsprovider = oqsprovider_sect

[default_sect]
activate = 1

[oqsprovider_sect]
activate = 1

Verify that your provider loads by default.

$ /usr/local/bin/openssl list -providers -verbose`
Providers:
  default
    name: OpenSSL Default Provider
    version: 3.3.2
    status: active
  oqsprovider
    name: OpenSSL OQS Provider
    version: 0.7.0
    status: active

If you only see the default provider, check your config for typos etc.

Then we can verify that we have a PQC capable setup using curl:

$ curl https://pq.cloudflareresearch.com/cdn-cgi/trace --curves X25519MLKEM768
fl=522f159
h=pq.cloudflareresearch.com
ip=192.0.1.7
ts=1733670505.942
visit_scheme=https
uag=curl/8.11.0
colo=AMS
sliver=none
http=http/2
loc=NL
tls=TLSv1.3
sni=plaintext
warp=off
gateway=off
rbi=off
kex=X25519MLKEM768

This validates two things:

  1. That your OpenSSL config has been picked up by curl, or it will errror out on the curve name.
  2. The response tells you that you've used a PQC key-exchange (kex).

Configure Apache httpd

Now that we know that we have OpenSSL all set up, we can move on to configuring Apache httpd.

This is a tiny task. We're starting with a config generated by Mozilla's SSL-configurator (only the relevant lines here for brevity).

# modern configuration
SSLProtocol             TLSv1.3
SSLOpenSSLConfCmd       Curves X25519:prime256v1:secp384r1

Simply extend the Curves configuration with the ML-KEM curve

# modern configuration
SSLProtocol             TLSv1.3
SSLOpenSSLConfCmd       Curves X25519MLKEM768:X25519:prime256v1:secp384r1

Restart your Apache service. When all's well, you now have a PQC functional webserver!

Validate that your server is using MLKEM768 with curl (output shortened)

$ curl -vo /dev/null --curves X25519MLKEM768 https://your.example.org/
...
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519MLKEM768 / id-ecPublicKey
...

Check the output to see that the SSL connection uses MLKEM768 hybrid mode.

Qualys SSL Labs is still oblivious to the concept of PQC it seems. Hope that that changes soon!

What's next?

Update 2024-12-09: The oqsprovider port is now available on FreeBSD.