May 2nd, 2025
So you want to try out post-quantum cryptography (PQC) like all the cool kids - what are your options? You could use Open Quantum Safe's various providers; you could use plain vanilla OpenSSL, so long as you use the most recent OpenSSL 3.5.0 release; or you could use Google's BoringSSL, as much as Google recommends against it.
If you're using Linux (and specifically Linux on Linode), you can follow, e.g., these instructions I provided previously, but as usual, I also like to get everything working on NetBSD, so let's give that a go:
PQC Using Open Quantum Safe
A few months ago, I imported the Open Quantum Safe OpenSSL provider into pkgsrc, and using that is straight forward:
# PKG_PATH="https://cdn.NetBSD.org/pub/pkgsrc/packages/NetBSD/$(uname -p)/$(uname -r|cut -f '1 2' -d.)/All/" # export PKG_PATH # pkg_add pkgin # pkgin -y install oqs-provider [...] # cat >>/etc/openssl/openssl.cnf <<EOF 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 module = /usr/pkg/lib/ossl-modules/oqsprovider.so EOF #
And that's really all. To verify that it's
working, ensure that the list of providers includes
the "OpenSSL OQS Provider" and your kem-algorithms include the NIST
FIPS-203 ML-KEM options:
$ openssl list -providers
Providers:
default
name: OpenSSL Default Provider
version: 3.0.12
status: active
oqsprovider
name: OpenSSL OQS Provider
version: 0.8.0
status: active
$ openssl list -kem-algorithms | grep -i mlkem768
mlkem768 @ oqsprovider
p384_mlkem768 @ oqsprovider
x448_mlkem768 @ oqsprovider
X25519MLKEM768 @ oqsprovider
SecP256r1MLKEM768 @ oqsprovider
$ You can now verify that you can speak PQC using the
TLS 1.3 hybrid key exchange X25519MLKEM768 by connecting to,
e.g., this website (or any of the other sites
using PQC):
$ openssl s_client -curves X25519MLKEM768 -connect www.netmeister.org:443 CONNECTED(00000005) [...]
To configure, e.g., apache,
you'd then add the following SSLOpenSSLConfCmd
directive to your httpd-ssl.conf file:
# PQC, requires oqs-provider (and OpenSSL >= 3.x) SSLProtocol +TLSv1.3 SSLOpenSSLConfCmd Curves X25519:X25519MLKEM768:SecP256r1MLKEM768:secp384r1:prime256v1
If your browser speaks PQC (check about:config ->
security.tls.enable_kyber in Firefox, chrome://flags/#enable-tls13-kyber
and chrome://flags/#use-ml-kem for
Chromium browsers) , you should then see your
connection use X25519MLKEM768:

Nice.
PQC Using BoringSSL
Google's BoringSSL,
created back in 2014 after the Heartbleed
vulnerability (ah, good times, good times), has had
support for post-quantum cryptography for a while,
being one of the early adopters of Kyber,
ML-KEM's predecessor. However, BoringSSL is not (yet)
available in pkgsrc, so
we'll have to build it ourselves.
The process isn't particularly difficult. We'll
need git-base,
cmake,
and ninja-build
as build requirements and then install BoringSSL into
/opt/boringssl:
$ sudo pkgin -y install git-base cmake ninja-build
[...]
$ git clone https://boringssl.googlesource.com/boringssl
[...]
$ cd boringssl
$ export PREFIX=/opt/boringssl
$ export LDFLAGS="-Wl,-rpath,${PREFIX}/lib"
$ cmake -GNinja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DCMAKE_INSTALL_PREFIX=${PREFIX}
[...]
-- Configuring done (1.2s)
-- Generating done (0.4s)
-- Build files have been written to: /root/boringssl/build
$ ninja -C build
ninja: Entering directory `build'
[560/638] Building CXX object CMakeFiles/ssl_test.dir/ssl/ssl_test.cc.o
[638/638] Linking CXX executable ssl_test
$ Well, that was easy - let's install it and see if it works:
$ sudo ninja -C build install [...] $ /opt/boringssl/bin/bssl s_client -connect www.netmeister.org -curves X25519MLKEM768 Connecting to [2602:f977:800:0:e276:63ff:fe72:3900]:443 Connected. Version: TLSv1.3 Cipher: TLS_AES_256_GCM_SHA384 ECDHE group: X25519MLKEM768 Signature algorithm: ecdsa_secp256r1_sha256 Cert subject: CN = netmeister.org Cert issuer: C = US, O = Let's Encrypt, CN = E6
Neat. Now let's actually use it with... say, nginx. We can't use
pkgsrc to install nginx, since we need to link it with
our new BoringSSL library, so we need to build it by
hand as well, using the configuration options taken
over from pkgsrc's
Makefile (modulo a different PREFIX) applying the minimally
required patch:
$ ftp https://nginx.org/download/nginx-1.28.0.tar.gz
[...]
$ ftp https://github.com/freenginx/nginx/commit/1ac658f44afc9240f13e9d6c1c9d5a7816299e8e.patch
[...]
$ tar zxf nginx-1.28.0.tar.gz
$ cd nginx-1.28.0
$ patch -p1 < ../1ac658f44afc9240f13e9d6c1c9d5a7816299e8e.patch
[...]
$ export PREFIX="/opt/nginx"
$ ./configure --user=nginx \
--group=nginx \
--prefix=${PREFIX} \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/db/nginx/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/db/nginx/client_body_temp \
--http-proxy-temp-path=/var/db/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/db/nginx/fstcgi_temp \
--http-scgi-temp-path=/var/db/nginx/scgi_temp \
--with-pcre \
--with-mail_ssl_module \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_realip_module \
--http-uwsgi-temp-path=/var/db/nginx/uwsgi_temp \
--with-http_slice_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_auth_request_module \
--with-openssl-opt=enable-tls1_3 \
--with-cc-opt='-I/usr/pkg/include -I/opt/boringssl/include' \
--with-ld-opt='-L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib' \
--with-ld-opt="-L${PREFIX}/lib -Wl,-rpath,${PREFIX}/lib" \
--with-ld-opt='-L/opt/boringssl/lib -Wl,-rpath,/opt/boringssl/lib'
[...]
$ make
[...]
$ sudo make install
[...]
You can then update /opt/nginx/conf/nginx.conf to add
a minimal TLS configuration:
server {
listen 443 ssl;
listen [::]:443 default_server ssl;
server_name example.com www.example.com;
root /var/www/pqc;
index index.html;
ssl_certificate /opt/certs/pqc.crt;
ssl_certificate_key /opt/certs/pqc.key;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519MLKEM768:X25519;
location / {
try_files $uri $uri/ =404;
}
} ...and just like before, you should see your connection use X25519MLKEM768:
$ /opt/boringssl/bin/bssl s_client -connect localhost -curves X25519MLKEM768 Connecting to [::1]:443 Connected. Version: TLSv1.3 Resumed session: no Cipher: TLS_AES_128_GCM_SHA256 ECDHE group: X25519MLKEM768 [...]
PQC - of course it runs NetBSD!
May 2nd, 2025
Links:

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.