Support X25519Kyber768Draft00 or X25519Kyber768
Your Feature Request
HAProxy should support at least one quantum safe encryption method for TLS connections. It seems that modern user agents (web browsers) are converging to support X25519Kyber768Draft00 as documented at https://pq.cloudflareresearch.com/
X25519Kyber768Draft00 with TLS identifier 0x6399 is already supported by Chrome and Edge and Firefox support is current compiled in but hidden behind user accessible config setting security.tls.enable_kyber and that config setting will probably default to true in near future.
X25519Kyber768Draft00 is combination of X25519 (already supported by HAProxy) and Kyber, where half (256 bits) of the session key is transferred via X25519 and the other half via Kyber in a single handshake. The handshake data transmission overhead compared to plain X25519 is about 2 KB and server needs about 4 KB of additional RAM to compute the Kyber part.
What are you trying to do?
I'm trying to connect to HAProxy using TLS 1.3 encryption method X25519Kyber768Draft00.
Output of haproxy -vv
HAProxy version 2.4.25-1ppa1~focal 2023/12/16 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.25.html
Running on: Linux 5.4.0-144-generic #161-Ubuntu SMP Fri Feb 3 14:49:04 UTC 2023 x86_64
Build options :
TARGET = linux-glibc
CPU = generic
CC = cc
CFLAGS = -O2 -g -O2 -fdebug-prefix-map=/build/haproxy-bt29EY/haproxy-2.4.25=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-address-of-packed-member -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-cast-function-type -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference
OPTIONS = USE_PCRE2=1 USE_PCRE2_JIT=1 USE_OPENSSL=1 USE_LUA=1 USE_SLZ=1 USE_SYSTEMD=1 USE_PROMEX=1
DEBUG =
Feature list : -51DEGREES +ACCEPT4 +BACKTRACE -CLOSEFROM +CPU_AFFINITY +CRYPT_H -DEVICEATLAS +DL +EPOLL -EVPORTS +FUTEX +GETADDRINFO -KQUEUE +LIBCRYPT +LINUX_SPLICE +LINUX_TPROXY +LUA -MEMORY_PROFILING +NETFILTER +NS -OBSOLETE_LINKER +OPENSSL -OT -PCRE +PCRE2 +PCRE2_JIT -PCRE_JIT +POLL +PRCTL -PRIVATE_CACHE -PROCCTL +PROMEX -PTHREAD_PSHARED -QUIC +RT +SLZ -STATIC_PCRE -STATIC_PCRE2 +SYSTEMD +TFO +THREAD +THREAD_DUMP +TPROXY -WURFL -ZLIB
Default settings :
bufsize = 16384, maxrewrite = 1024, maxpollevents = 200
Built with multi-threading support (MAX_THREADS=64, default=8).
Built with OpenSSL version : OpenSSL 1.1.1f 31 Mar 2020
Running on OpenSSL version : OpenSSL 1.1.1f 31 Mar 2020
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.3
Built with the Prometheus exporter as a service
Built with network namespace support.
Built with libslz for stateless compression.
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE2 version : 10.34 2019-11-21
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with gcc compiler version 9.4.0
Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.
Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
h2 : mode=HTTP side=FE|BE mux=H2 flags=HTX|CLEAN_ABRT|HOL_RISK|NO_UPG
fcgi : mode=HTTP side=BE mux=FCGI flags=HTX|HOL_RISK|NO_UPG
<default> : mode=HTTP side=FE|BE mux=H1 flags=HTX
h1 : mode=HTTP side=FE|BE mux=H1 flags=HTX|NO_UPG
<default> : mode=TCP side=FE|BE mux=PASS flags=
none : mode=TCP side=FE|BE mux=PASS flags=NO_UPG
Available services : prometheus-exporter
Available filters :
[SPOE] spoe
[CACHE] cache
[FCGI] fcgi-app
[COMP] compression
[TRACE] trace
I don't know much about X25519Kyber768 and post-quantum but this look like something that would need to be supported in the SSL library and not in haproxy. We don't do anything for X25519 in HAProxy for example, it's only a curves feature which is exposed by OpenSSL and that can be configured in haproxy configuration.
The handshake is not something which is written in HAProxy but completely in OpenSSL, we only have some callback to handle SNI selection or storing SSL sessions, but we don't do much crypto ourselves. But if something is missing in HAProxy to make it work, we could take a look.
Do you have some experience with this? Is this supposed to be working with openssl ? I'm seeing a provider for openssl 3.x https://github.com/open-quantum-safe/oqs-provider/ . There is a directive for haproxy to load a provider http://docs.haproxy.org/3.0/configuration.html#ssl-provider and to set its configuration http://docs.haproxy.org/3.0/configuration.html#ssl-propquery .
It seems that Google has implemented this in BoringSSL just for this reason. BoringSSL is a fork of OpenSSL that is designed to meet Google's needs.
I guess in theory it would be possible to compile HAProxy against BoringSSL instead of OpenSSL and get this feature for free, but I don't know how much other issues that might bring.
It's good to know that HAProxy doesn't implement anything special internally for this so it would automatically learn this new feature if OpenSSL incorporates the required patches.
This commit probably points to all the places that would need to be patched in OpenSSL for this to happen: https://github.com/google/boringssl/commit/e491eeb610fcc69b98bc6d1ba08faf78655808f6
BoringSSL has following disclaimer which suggests that building against it shouldn't be considered a long-term solution:
Although BoringSSL is an open source project, it is not intended for general use, as OpenSSL is. We don't recommend that third parties depend upon it. Doing so is likely to be frustrating because there are no guarantees of API or ABI stability.
I'll see if OpenSSL already has an issue raised for this and if not, I'll create one.
We know about boringSSL and we supported it at some point, but given its development cycle and its lack of maintenance version, we dropped it after a lot of breakage of their API. Today we are not willing to support it actively, as it require much more work to make it work. but people from the community can contribute if they really want it.
Supported SSL libraries are listed there: https://github.com/haproxy/wiki/wiki/SSL-Libraries-Support-Status.
I made some research about the Open Quantum Safe provider, and found an article about how to make it work with nginx: https://blog.aegrel.ee/kyber-nginx.html
That kind of setup is supported with HAProxy, so loading the provider with the ssl-provider primitive and configuring the curves keyword with x25519_kyber768:p384_kyber768:... should be enough to make this work.
FYI I added a minimalist example at https://github.com/haproxy/wiki/wiki/OpenSSL-Providers-in-HAProxy#oqsprovider---open-quantum-safe-provider. I tested the provider successfully.