haproxy icon indicating copy to clipboard operation
haproxy copied to clipboard

Support X25519Kyber768Draft00 or X25519Kyber768

Open mikkorantalainen opened this issue 1 year ago • 3 comments

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

mikkorantalainen avatar Jun 11 '24 13:06 mikkorantalainen

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 .

wlallemand avatar Jun 11 '24 20:06 wlallemand

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.

mikkorantalainen avatar Jun 12 '24 06:06 mikkorantalainen

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.

wlallemand avatar Jun 12 '24 07:06 wlallemand

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.

wlallemand avatar Aug 07 '24 08:08 wlallemand