Skip to content

ECH and ESNI support in picotls

Christian Huitema edited this page Nov 16, 2023 · 2 revisions

Encrypted Server Name Indication for TLS 1.3 (ESNI) is an extension to TLS 1.3 that sends the server name in an encrypted form. In later drafts, the ESNI specification evolved into Encrypted Client Hello.

Early versions of picotls supported working group draft-02, but the new versions support ECH. The documentation below is out of date.

1. Setup

1.1. Generating ESNI Keys

Use openssl 1.1.0 or above to generate a ESNI private key using X25519 or secp256r1.

% openssl genpkey -algorithm x25519 > esni-x25519.key
% openssl ecparam -name secp256r1 -genkey -noout -out esni-secp256r1.key

OpenSSL 1.1.0 or above is required for generating X25519 keys.

1.2. Generating a ESNI Resource Record

Use the picotls-esni command to build a ESNI Resource Record. The command takes the private key(s) and the cipher-suites to be supported for encrypting the ESNI extension.

The example below creates a ESNI Resource Record that contains two private keys and declares support for two cipher-suites.

% picotls-esni -K esni-x25519.key -K esni-secp256r1.key -c aes128-gcm -c chacha20-poly1305 > esni-rr.bin

See picotls-esni -h to find other options.

The generated ESNI Resource Record must be deployed to the authoritative DNS server using the TXT record type, with the _esni prefix.

2. Using the "cli" Command

2.1. Running the Server

As a server, the "cli" command accepts two options that are used for Encrypted SNI.

-E option specifies the filename of the ESNI Resource Record. -K option specifies the filename of the ESNI private key. The option can be used more than once to specify multiple keys.

The example below launches a TLS server running at 127.0.0.1:4433 using the keys and the Resource Record being generated in the examples above.

% ./cli -K esni-x25519.key -K esni-secp256r1.key -E esni-rr.bin -k server.key -c server.crt 127.0.0.1 4433

2.1. Running the Client

There is no change to how the command is being run in client mode. The command automatically resolves the ESNI key associated to the server it connects to, by calling res_query.

% ./cli 127.0.0.1 4433

3. API

3.1. Server-side API

ptls_context_t::esni is a NULL-terminated list of ESNI contexts. Each ESNI context contains a list of key exnchanges, as well as the information to be found in the ESNI Resource Record (e.g., cipher-suites, padded-length).

For building the ESNI context, a helper function called ptls_esni_init_context is provided. The function accepts a ptls_iovec_t specifying the ESNI Resource Record and a NULL-terminated list of key exchanges.

Its use can be found in the setup_esni function in t/util.h.

4.1. Client-side API

An application that is willing to use ESNI should setup ptls_handshake_properties_t::client.esni_keys to point to the ESNI Resource Record of the server the application is going to connect to. If set, picotls will parse the provided Resource Record and use the Encrypted SNI extension.