xref: /aosp_15_r20/external/curl/docs/ECH.md (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker<!--
2*6236dae4SAndroid Build Coastguard WorkerCopyright (C) Daniel Stenberg, <[email protected]>, et al.
3*6236dae4SAndroid Build Coastguard Worker
4*6236dae4SAndroid Build Coastguard WorkerSPDX-License-Identifier: curl
5*6236dae4SAndroid Build Coastguard Worker-->
6*6236dae4SAndroid Build Coastguard Worker
7*6236dae4SAndroid Build Coastguard Worker# Building curl with HTTPS-RR and ECH support
8*6236dae4SAndroid Build Coastguard Worker
9*6236dae4SAndroid Build Coastguard WorkerWe have added support for ECH to curl. It can use HTTPS RRs published in the
10*6236dae4SAndroid Build Coastguard WorkerDNS if curl uses DoH, or else can accept the relevant ECHConfigList values
11*6236dae4SAndroid Build Coastguard Workerfrom the command line. This works with OpenSSL, wolfSSL or BoringSSL as the
12*6236dae4SAndroid Build Coastguard WorkerTLS provider.
13*6236dae4SAndroid Build Coastguard Worker
14*6236dae4SAndroid Build Coastguard WorkerThis feature is EXPERIMENTAL. DO NOT USE IN PRODUCTION.
15*6236dae4SAndroid Build Coastguard Worker
16*6236dae4SAndroid Build Coastguard WorkerThis should however provide enough of a proof-of-concept to prompt an informed
17*6236dae4SAndroid Build Coastguard Workerdiscussion about a good path forward for ECH support in curl.
18*6236dae4SAndroid Build Coastguard Worker
19*6236dae4SAndroid Build Coastguard Worker## OpenSSL Build
20*6236dae4SAndroid Build Coastguard Worker
21*6236dae4SAndroid Build Coastguard WorkerTo build our ECH-enabled OpenSSL fork:
22*6236dae4SAndroid Build Coastguard Worker
23*6236dae4SAndroid Build Coastguard Worker```bash
24*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
25*6236dae4SAndroid Build Coastguard Worker    git clone https://github.com/defo-project/openssl
26*6236dae4SAndroid Build Coastguard Worker    cd openssl
27*6236dae4SAndroid Build Coastguard Worker    ./config --libdir=lib --prefix=$HOME/code/openssl-local-inst
28*6236dae4SAndroid Build Coastguard Worker    ...stuff...
29*6236dae4SAndroid Build Coastguard Worker    make -j8
30*6236dae4SAndroid Build Coastguard Worker    ...stuff (maybe go for coffee)...
31*6236dae4SAndroid Build Coastguard Worker    make install_sw
32*6236dae4SAndroid Build Coastguard Worker    ...a little bit of stuff...
33*6236dae4SAndroid Build Coastguard Worker```
34*6236dae4SAndroid Build Coastguard Worker
35*6236dae4SAndroid Build Coastguard WorkerTo build curl ECH-enabled, making use of the above:
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker```bash
38*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
39*6236dae4SAndroid Build Coastguard Worker    git clone https://github.com/curl/curl
40*6236dae4SAndroid Build Coastguard Worker    cd curl
41*6236dae4SAndroid Build Coastguard Worker    autoreconf -fi
42*6236dae4SAndroid Build Coastguard Worker    LDFLAGS="-Wl,-rpath,$HOME/code/openssl-local-inst/lib/" ./configure --with-ssl=$HOME/code/openssl-local-inst --enable-ech --enable-httpsrr
43*6236dae4SAndroid Build Coastguard Worker    ...lots of output...
44*6236dae4SAndroid Build Coastguard Worker    WARNING: ECH HTTPSRR enabled but marked EXPERIMENTAL...
45*6236dae4SAndroid Build Coastguard Worker    make
46*6236dae4SAndroid Build Coastguard Worker    ...lots more output...
47*6236dae4SAndroid Build Coastguard Worker```
48*6236dae4SAndroid Build Coastguard Worker
49*6236dae4SAndroid Build Coastguard WorkerIf you do not get that WARNING at the end of the ``configure`` command, then
50*6236dae4SAndroid Build Coastguard WorkerECH is not enabled, so go back some steps and re-do whatever needs re-doing:-)
51*6236dae4SAndroid Build Coastguard WorkerIf you want to debug curl then you should add ``--enable-debug`` to the
52*6236dae4SAndroid Build Coastguard Worker``configure`` command.
53*6236dae4SAndroid Build Coastguard Worker
54*6236dae4SAndroid Build Coastguard WorkerIn a recent (2024-05-20) build on one machine, configure failed to find the
55*6236dae4SAndroid Build Coastguard WorkerECH-enabled SSL library, apparently due to the existence of
56*6236dae4SAndroid Build Coastguard Worker``$HOME/code/openssl-local-inst/lib/pkgconfig`` as a directory containing
57*6236dae4SAndroid Build Coastguard Workervarious settings. Deleting that directory worked around the problem but may
58*6236dae4SAndroid Build Coastguard Workernot be the best solution.
59*6236dae4SAndroid Build Coastguard Worker
60*6236dae4SAndroid Build Coastguard Worker## Using ECH and DoH
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard WorkerCurl supports using DoH for A/AAAA lookups so it was relatively easy to add
63*6236dae4SAndroid Build Coastguard Workerretrieval of HTTPS RRs in that situation. To use ECH and DoH together:
64*6236dae4SAndroid Build Coastguard Worker
65*6236dae4SAndroid Build Coastguard Worker```bash
66*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code/curl
67*6236dae4SAndroid Build Coastguard Worker    LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl --ech true --doh-url https://one.one.one.one/dns-query https://defo.ie/ech-check.php
68*6236dae4SAndroid Build Coastguard Worker    ...
69*6236dae4SAndroid Build Coastguard Worker    SSL_ECH_STATUS: success <img src="greentick-small.png" alt="good" /> <br/>
70*6236dae4SAndroid Build Coastguard Worker    ...
71*6236dae4SAndroid Build Coastguard Worker```
72*6236dae4SAndroid Build Coastguard Worker
73*6236dae4SAndroid Build Coastguard WorkerThe output snippet above is within the HTML for the webpage, when things work.
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard WorkerThe above works for these test sites:
76*6236dae4SAndroid Build Coastguard Worker
77*6236dae4SAndroid Build Coastguard Worker```bash
78*6236dae4SAndroid Build Coastguard Worker    https://defo.ie/ech-check.php
79*6236dae4SAndroid Build Coastguard Worker    https://draft-13.esni.defo.ie:8413/stats
80*6236dae4SAndroid Build Coastguard Worker    https://draft-13.esni.defo.ie:8414/stats
81*6236dae4SAndroid Build Coastguard Worker    https://crypto.cloudflare.com/cdn-cgi/trace
82*6236dae4SAndroid Build Coastguard Worker    https://tls-ech.dev
83*6236dae4SAndroid Build Coastguard Worker```
84*6236dae4SAndroid Build Coastguard Worker
85*6236dae4SAndroid Build Coastguard WorkerThe list above has 4 different server technologies, implemented by 3 different
86*6236dae4SAndroid Build Coastguard Workerparties, and includes a case (the port 8414 server) where HelloRetryRequest
87*6236dae4SAndroid Build Coastguard Worker(HRR) is forced.
88*6236dae4SAndroid Build Coastguard Worker
89*6236dae4SAndroid Build Coastguard WorkerWe currently support the following new curl command line arguments/options:
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker- ``--ech <config>`` - the ``config`` value can be one of:
92*6236dae4SAndroid Build Coastguard Worker    - ``false`` says to not attempt ECH
93*6236dae4SAndroid Build Coastguard Worker    - ``true`` says to attempt ECH, if possible
94*6236dae4SAndroid Build Coastguard Worker    - ``grease`` if attempting ECH is not possible, then send a GREASE ECH extension
95*6236dae4SAndroid Build Coastguard Worker    - ``hard`` hard-fail the connection if ECH cannot be attempted
96*6236dae4SAndroid Build Coastguard Worker    - ``ecl:<b64value>`` a base64 encoded ECHConfigList, rather than one accessed from the DNS
97*6236dae4SAndroid Build Coastguard Worker    - ``pn:<name>`` override the ``public_name`` from an ECHConfigList
98*6236dae4SAndroid Build Coastguard Worker
99*6236dae4SAndroid Build Coastguard WorkerNote that in the above "attempt ECH" means the client emitting a TLS
100*6236dae4SAndroid Build Coastguard WorkerClientHello with a "real" ECH extension, but that does not mean that the
101*6236dae4SAndroid Build Coastguard Workerrelevant server can succeed in decrypting, as things can fail for other
102*6236dae4SAndroid Build Coastguard Workerreasons.
103*6236dae4SAndroid Build Coastguard Worker
104*6236dae4SAndroid Build Coastguard Worker## Supplying an ECHConfigList on the command line
105*6236dae4SAndroid Build Coastguard Worker
106*6236dae4SAndroid Build Coastguard WorkerTo supply the ECHConfigList on the command line, you might need a bit of
107*6236dae4SAndroid Build Coastguard Workercut-and-paste, e.g.:
108*6236dae4SAndroid Build Coastguard Worker
109*6236dae4SAndroid Build Coastguard Worker```bash
110*6236dae4SAndroid Build Coastguard Worker    dig +short https defo.ie
111*6236dae4SAndroid Build Coastguard Worker    1 . ipv4hint=213.108.108.101 ech=AED+DQA8PAAgACD8WhlS7VwEt5bf3lekhHvXrQBGDrZh03n/LsNtAodbUAAEAAEAAQANY292ZXIuZGVmby5pZQAA ipv6hint=2a00:c6c0:0:116:5::10
112*6236dae4SAndroid Build Coastguard Worker```
113*6236dae4SAndroid Build Coastguard Worker
114*6236dae4SAndroid Build Coastguard WorkerThen paste the base64 encoded ECHConfigList onto the curl command line:
115*6236dae4SAndroid Build Coastguard Worker
116*6236dae4SAndroid Build Coastguard Worker```bash
117*6236dae4SAndroid Build Coastguard Worker    LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl --ech ecl:AED+DQA8PAAgACD8WhlS7VwEt5bf3lekhHvXrQBGDrZh03n/LsNtAodbUAAEAAEAAQANY292ZXIuZGVmby5pZQAA https://defo.ie/ech-check.php
118*6236dae4SAndroid Build Coastguard Worker    ...
119*6236dae4SAndroid Build Coastguard Worker    SSL_ECH_STATUS: success <img src="greentick-small.png" alt="good" /> <br/>
120*6236dae4SAndroid Build Coastguard Worker    ...
121*6236dae4SAndroid Build Coastguard Worker```
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard WorkerThe output snippet above is within the HTML for the webpage.
124*6236dae4SAndroid Build Coastguard Worker
125*6236dae4SAndroid Build Coastguard WorkerIf you paste in the wrong ECHConfigList (it changes hourly for ``defo.ie``) you
126*6236dae4SAndroid Build Coastguard Workershould get an error like this:
127*6236dae4SAndroid Build Coastguard Worker
128*6236dae4SAndroid Build Coastguard Worker```bash
129*6236dae4SAndroid Build Coastguard Worker    LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl -vvv --ech ecl:AED+DQA8yAAgACDRMQo+qYNsNRNj+vfuQfFIkrrUFmM4vogucxKj/4nzYgAEAAEAAQANY292ZXIuZGVmby5pZQAA https://defo.ie/ech-check.php
130*6236dae4SAndroid Build Coastguard Worker    ...
131*6236dae4SAndroid Build Coastguard Worker    * OpenSSL/3.3.0: error:0A00054B:SSL routines::ech required
132*6236dae4SAndroid Build Coastguard Worker    ...
133*6236dae4SAndroid Build Coastguard Worker```
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard WorkerThere is a reason to want this command line option - for use before publishing
136*6236dae4SAndroid Build Coastguard Workeran ECHConfigList in the DNS as per the Internet-draft [A well-known URI for
137*6236dae4SAndroid Build Coastguard Workerpublishing ECHConfigList values](https://datatracker.ietf.org/doc/draft-ietf-tls-wkech/).
138*6236dae4SAndroid Build Coastguard Worker
139*6236dae4SAndroid Build Coastguard WorkerIf you do use a wrong ECHConfigList value, then the server might return a
140*6236dae4SAndroid Build Coastguard Workergood value, via the ``retry_configs`` mechanism. You can see that value in
141*6236dae4SAndroid Build Coastguard Workerthe verbose output, e.g.:
142*6236dae4SAndroid Build Coastguard Worker
143*6236dae4SAndroid Build Coastguard Worker```bash
144*6236dae4SAndroid Build Coastguard Worker    LD_LIBRARY_PATH=$HOME/code/openssl ./src/curl -vvv --ech ecl:AED+DQA8yAAgACDRMQo+qYNsNRNj+vfuQfFIkrrUFmM4vogucxKj/4nzYgAEAAEAAQANY292ZXIuZGVmby5pZQAA https://defo.ie/ech-check.php
145*6236dae4SAndroid Build Coastguard Worker    ...
146*6236dae4SAndroid Build Coastguard Worker* ECH: retry_configs AQD+DQA8DAAgACBvYqJy+Hgk33wh/ZLBzKSPgwxeop7gvojQzfASq7zeZQAEAAEAAQANY292ZXIuZGVmby5pZQAA/g0APEMAIAAgXkT5r4cYs8z19q5rdittyIX8gfQ3ENW4wj1fVoiJZBoABAABAAEADWNvdmVyLmRlZm8uaWUAAP4NADw2ACAAINXSE9EdXzEQIJZA7vpwCIQsWqsFohZARXChgPsnfI1kAAQAAQABAA1jb3Zlci5kZWZvLmllAAD+DQA8cQAgACASeiD5F+UoSnVoHvA2l1EifUVMFtbVZ76xwDqmMPraHQAEAAEAAQANY292ZXIuZGVmby5pZQAA
147*6236dae4SAndroid Build Coastguard Worker* ECH: retry_configs for defo.ie from cover.defo.ie, 319
148*6236dae4SAndroid Build Coastguard Worker    ...
149*6236dae4SAndroid Build Coastguard Worker```
150*6236dae4SAndroid Build Coastguard Worker
151*6236dae4SAndroid Build Coastguard WorkerAt that point, you could copy the base64 encoded value above and try again.
152*6236dae4SAndroid Build Coastguard WorkerFor now, this only works for the OpenSSL and BoringSSL builds.
153*6236dae4SAndroid Build Coastguard Worker
154*6236dae4SAndroid Build Coastguard Worker## Default settings
155*6236dae4SAndroid Build Coastguard Worker
156*6236dae4SAndroid Build Coastguard WorkerCurl has various ways to configure default settings, e.g. in ``$HOME/.curlrc``,
157*6236dae4SAndroid Build Coastguard Workerso one can set the DoH URL and enable ECH that way:
158*6236dae4SAndroid Build Coastguard Worker
159*6236dae4SAndroid Build Coastguard Worker```bash
160*6236dae4SAndroid Build Coastguard Worker    cat ~/.curlrc
161*6236dae4SAndroid Build Coastguard Worker    doh-url=https://one.one.one.one/dns-query
162*6236dae4SAndroid Build Coastguard Worker    silent
163*6236dae4SAndroid Build Coastguard Worker    ech=true
164*6236dae4SAndroid Build Coastguard Worker```
165*6236dae4SAndroid Build Coastguard Worker
166*6236dae4SAndroid Build Coastguard WorkerNote that when you use the system's curl command (rather than our ECH-enabled
167*6236dae4SAndroid Build Coastguard Workerbuild), it is liable to warn that ``ech`` is an unknown option. If that is an
168*6236dae4SAndroid Build Coastguard Workerissue (e.g. if some script re-directs stdout and stderr somewhere) then adding
169*6236dae4SAndroid Build Coastguard Workerthe ``silent`` line above seems to be a good enough fix. (Though of
170*6236dae4SAndroid Build Coastguard Workercourse, yet another script could depend on non-silent behavior, so you may have
171*6236dae4SAndroid Build Coastguard Workerto figure out what you prefer yourself.) That seems to have changed with the
172*6236dae4SAndroid Build Coastguard Workerlatest build, previously ``silent=TRUE`` was what I used in ``~/.curlrc`` but
173*6236dae4SAndroid Build Coastguard Workernow that seems to cause a problem, so that the following line(s) are ignored.
174*6236dae4SAndroid Build Coastguard Worker
175*6236dae4SAndroid Build Coastguard WorkerIf you want to always use our OpenSSL build you can set ``LD_LIBRARY_PATH``
176*6236dae4SAndroid Build Coastguard Workerin the environment:
177*6236dae4SAndroid Build Coastguard Worker
178*6236dae4SAndroid Build Coastguard Worker```bash
179*6236dae4SAndroid Build Coastguard Worker    export LD_LIBRARY_PATH=$HOME/code/openssl
180*6236dae4SAndroid Build Coastguard Worker```
181*6236dae4SAndroid Build Coastguard Worker
182*6236dae4SAndroid Build Coastguard WorkerWhen you do the above, there can be a mismatch between OpenSSL versions
183*6236dae4SAndroid Build Coastguard Workerfor applications that check that. A ``git push`` for example fails so you
184*6236dae4SAndroid Build Coastguard Workershould unset ``LD_LIBRARY_PATH`` before doing that or use a different shell.
185*6236dae4SAndroid Build Coastguard Worker
186*6236dae4SAndroid Build Coastguard Worker```bash
187*6236dae4SAndroid Build Coastguard Worker    git push
188*6236dae4SAndroid Build Coastguard Worker    OpenSSL version mismatch. Built against 30000080, you have 30200000
189*6236dae4SAndroid Build Coastguard Worker    ...
190*6236dae4SAndroid Build Coastguard Worker```
191*6236dae4SAndroid Build Coastguard Worker
192*6236dae4SAndroid Build Coastguard WorkerWith all that setup as above the command line gets simpler:
193*6236dae4SAndroid Build Coastguard Worker
194*6236dae4SAndroid Build Coastguard Worker```bash
195*6236dae4SAndroid Build Coastguard Worker    ./src/curl https://defo.ie/ech-check.php
196*6236dae4SAndroid Build Coastguard Worker    ...
197*6236dae4SAndroid Build Coastguard Worker    SSL_ECH_STATUS: success <img src="greentick-small.png" alt="good" /> <br/>
198*6236dae4SAndroid Build Coastguard Worker    ...
199*6236dae4SAndroid Build Coastguard Worker```
200*6236dae4SAndroid Build Coastguard Worker
201*6236dae4SAndroid Build Coastguard WorkerThe ``--ech true`` option is opportunistic, so tries to do ECH but does not fail if
202*6236dae4SAndroid Build Coastguard Workerthe client for example cannot find any ECHConfig values. The ``--ech hard``
203*6236dae4SAndroid Build Coastguard Workeroption hard-fails if there is no ECHConfig found in DNS, so for now, that is not
204*6236dae4SAndroid Build Coastguard Workera good option to set as a default. Once ECH has really been attempted by
205*6236dae4SAndroid Build Coastguard Workerthe client, if decryption on the server side fails, then curl fails.
206*6236dae4SAndroid Build Coastguard Worker
207*6236dae4SAndroid Build Coastguard Worker## Code changes for ECH support when using DoH
208*6236dae4SAndroid Build Coastguard Worker
209*6236dae4SAndroid Build Coastguard WorkerCode changes are ``#ifdef`` protected via ``USE_ECH`` or ``USE_HTTPSRR``:
210*6236dae4SAndroid Build Coastguard Worker
211*6236dae4SAndroid Build Coastguard Worker- ``USE_HTTPSRR`` is used for HTTPS RR retrieval code that could be generically
212*6236dae4SAndroid Build Coastguard Worker  used should non-ECH uses for HTTPS RRs be identified, e.g. use of ALPN values
213*6236dae4SAndroid Build Coastguard Workeror IP address hints.
214*6236dae4SAndroid Build Coastguard Worker
215*6236dae4SAndroid Build Coastguard Worker- ``USE_ECH`` protects ECH specific code.
216*6236dae4SAndroid Build Coastguard Worker
217*6236dae4SAndroid Build Coastguard WorkerThere are various obvious code blocks for handling the new command line
218*6236dae4SAndroid Build Coastguard Workerarguments which are not described here, but should be fairly clear.
219*6236dae4SAndroid Build Coastguard Worker
220*6236dae4SAndroid Build Coastguard WorkerAs shown in the ``configure`` usage above, there are ``configure.ac`` changes
221*6236dae4SAndroid Build Coastguard Workerthat allow separately dis/enabling ``USE_HTTPSRR`` and ``USE_ECH``. If ``USE_ECH``
222*6236dae4SAndroid Build Coastguard Workeris enabled, then ``USE_HTTPSRR`` is forced. In both cases ``USE_DOH``
223*6236dae4SAndroid Build Coastguard Workeris required. (There may be some configuration conflicts available for the
224*6236dae4SAndroid Build Coastguard Workerdetermined:-)
225*6236dae4SAndroid Build Coastguard Worker
226*6236dae4SAndroid Build Coastguard WorkerThe main functional change, as you would expect, is in ``lib/vtls/openssl.c``
227*6236dae4SAndroid Build Coastguard Workerwhere an ECHConfig, if available from command line or DNS cache, is fed into
228*6236dae4SAndroid Build Coastguard Workerthe OpenSSL library via the new APIs implemented in our OpenSSL fork for that
229*6236dae4SAndroid Build Coastguard Workerpurpose. This code also implements the opportunistic (``--ech true``) or hard-fail
230*6236dae4SAndroid Build Coastguard Worker(``--ech hard``) logic.
231*6236dae4SAndroid Build Coastguard Worker
232*6236dae4SAndroid Build Coastguard WorkerOther than that, the main additions are in ``lib/doh.c``
233*6236dae4SAndroid Build Coastguard Workerwhere we reuse ``dohprobe()`` to retrieve an HTTPS RR value for the target
234*6236dae4SAndroid Build Coastguard Workerdomain. If such a value is found, that is stored using a new ``doh_store_https()``
235*6236dae4SAndroid Build Coastguard Workerfunction in a new field in the ``dohentry`` structure.
236*6236dae4SAndroid Build Coastguard Worker
237*6236dae4SAndroid Build Coastguard WorkerThe qname for the DoH query is modified if the port number is not 443, as
238*6236dae4SAndroid Build Coastguard Workerdefined in the SVCB specification.
239*6236dae4SAndroid Build Coastguard Worker
240*6236dae4SAndroid Build Coastguard WorkerWhen the DoH process has worked, ``Curl_doh_is_resolved()`` now also returns
241*6236dae4SAndroid Build Coastguard Workerthe relevant HTTPS RR value data in the ``Curl_dns_entry`` structure.
242*6236dae4SAndroid Build Coastguard WorkerThat is later accessed when the TLS session is being established, if ECH is
243*6236dae4SAndroid Build Coastguard Workerenabled (from ``lib/vtls/openssl.c`` as described above).
244*6236dae4SAndroid Build Coastguard Worker
245*6236dae4SAndroid Build Coastguard Worker## Limitations
246*6236dae4SAndroid Build Coastguard Worker
247*6236dae4SAndroid Build Coastguard WorkerThings that need fixing, but that can probably be ignored for the
248*6236dae4SAndroid Build Coastguard Workermoment:
249*6236dae4SAndroid Build Coastguard Worker
250*6236dae4SAndroid Build Coastguard Worker- We could easily add code to make use of an ``alpn=`` value found in an HTTPS
251*6236dae4SAndroid Build Coastguard Worker  RR, passing that on to OpenSSL for use as the "inner" ALPN value, but have
252*6236dae4SAndroid Build Coastguard Workeryet to do that.
253*6236dae4SAndroid Build Coastguard Worker
254*6236dae4SAndroid Build Coastguard WorkerCurrent limitations (more interesting than the above):
255*6236dae4SAndroid Build Coastguard Worker
256*6236dae4SAndroid Build Coastguard Worker- Only the first HTTPS RR value retrieved is actually processed as described
257*6236dae4SAndroid Build Coastguard Worker  above, that could be extended in future, though picking the "right" HTTPS RR
258*6236dae4SAndroid Build Coastguard Workercould be non-trivial if multiple RRs are published - matching IP address hints
259*6236dae4SAndroid Build Coastguard Workerversus A/AAAA values might be a good basis for that. Last I checked though,
260*6236dae4SAndroid Build Coastguard Workerbrowsers supporting ECH did not handle multiple HTTPS RRs well, though that
261*6236dae4SAndroid Build Coastguard Workerneeds re-checking as it has been a while.
262*6236dae4SAndroid Build Coastguard Worker
263*6236dae4SAndroid Build Coastguard Worker- It is unclear how one should handle any IP address hints found in an HTTPS RR.
264*6236dae4SAndroid Build Coastguard Worker  It may be that a bit of consideration of how "multi-CDN" deployments might
265*6236dae4SAndroid Build Coastguard Workeremerge would provide good answers there, but for now, it is not clear how best
266*6236dae4SAndroid Build Coastguard Workercurl might handle those values when present in the DNS.
267*6236dae4SAndroid Build Coastguard Worker
268*6236dae4SAndroid Build Coastguard Worker- The SVCB/HTTPS RR specification supports a new "CNAME at apex" indirection
269*6236dae4SAndroid Build Coastguard Worker  ("aliasMode") - the current code takes no account of that at all. One could
270*6236dae4SAndroid Build Coastguard Workerenvisage implementing the equivalent of following CNAMEs in such cases, but
271*6236dae4SAndroid Build Coastguard Workerit is not clear if that'd be a good plan. (As of now, chrome browsers do not seem
272*6236dae4SAndroid Build Coastguard Workerto have any support for that "aliasMode" and we have not checked Firefox for that
273*6236dae4SAndroid Build Coastguard Workerrecently.)
274*6236dae4SAndroid Build Coastguard Worker
275*6236dae4SAndroid Build Coastguard Worker- We have not investigated what related changes or additions might be needed
276*6236dae4SAndroid Build Coastguard Worker  for applications using libcurl, as opposed to use of curl as a command line
277*6236dae4SAndroid Build Coastguard Workertool.
278*6236dae4SAndroid Build Coastguard Worker
279*6236dae4SAndroid Build Coastguard Worker- We have not yet implemented tests as part of the usual curl test harness as
280*6236dae4SAndroid Build Coastguard Workerdoing so would seem to require re-implementing an ECH-enabled server as part
281*6236dae4SAndroid Build Coastguard Workerof the curl test harness. For now, we have a ``./tests/ech_test.sh`` script
282*6236dae4SAndroid Build Coastguard Workerthat attempts ECH with various test servers and with many combinations of the
283*6236dae4SAndroid Build Coastguard Workerallowed command line options. While that is a useful test and has find issues,
284*6236dae4SAndroid Build Coastguard Workerit is not comprehensive and we are not (as yet) sure what would be the right
285*6236dae4SAndroid Build Coastguard Workerlevel of coverage. When running that script you should not have a
286*6236dae4SAndroid Build Coastguard Worker``$HOME/.curlrc`` file that affects ECH or some of the negative tests could
287*6236dae4SAndroid Build Coastguard Workerproduce spurious failures.
288*6236dae4SAndroid Build Coastguard Worker
289*6236dae4SAndroid Build Coastguard Worker## Building with cmake
290*6236dae4SAndroid Build Coastguard Worker
291*6236dae4SAndroid Build Coastguard WorkerTo build with cmake, assuming our ECH-enabled OpenSSL is as before:
292*6236dae4SAndroid Build Coastguard Worker
293*6236dae4SAndroid Build Coastguard Worker```bash
294*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
295*6236dae4SAndroid Build Coastguard Worker    git clone https://github.com/curl/curl
296*6236dae4SAndroid Build Coastguard Worker    cd curl
297*6236dae4SAndroid Build Coastguard Worker    mkdir build
298*6236dae4SAndroid Build Coastguard Worker    cd build
299*6236dae4SAndroid Build Coastguard Worker    cmake -DOPENSSL_ROOT_DIR=$HOME/code/openssl -DUSE_ECH=1 -DUSE_HTTPSRR=1 ..
300*6236dae4SAndroid Build Coastguard Worker    ...
301*6236dae4SAndroid Build Coastguard Worker    make
302*6236dae4SAndroid Build Coastguard Worker    ...
303*6236dae4SAndroid Build Coastguard Worker    [100%] Built target curl
304*6236dae4SAndroid Build Coastguard Worker```
305*6236dae4SAndroid Build Coastguard Worker
306*6236dae4SAndroid Build Coastguard WorkerThe binary produced by the cmake build does not need any ECH-specific
307*6236dae4SAndroid Build Coastguard Worker``LD_LIBRARY_PATH`` setting.
308*6236dae4SAndroid Build Coastguard Worker
309*6236dae4SAndroid Build Coastguard Worker## BoringSSL build
310*6236dae4SAndroid Build Coastguard Worker
311*6236dae4SAndroid Build Coastguard WorkerBoringSSL is also supported by curl and also supports ECH, so to build
312*6236dae4SAndroid Build Coastguard Workerwith that, instead of our ECH-enabled OpenSSL:
313*6236dae4SAndroid Build Coastguard Worker
314*6236dae4SAndroid Build Coastguard Worker```bash
315*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
316*6236dae4SAndroid Build Coastguard Worker    git clone https://boringssl.googlesource.com/boringssl
317*6236dae4SAndroid Build Coastguard Worker    cd boringssl
318*6236dae4SAndroid Build Coastguard Worker    cmake -DCMAKE_INSTALL_PREFIX:PATH=$HOME/code/boringssl/inst -DBUILD_SHARED_LIBS=1
319*6236dae4SAndroid Build Coastguard Worker    make
320*6236dae4SAndroid Build Coastguard Worker    ...
321*6236dae4SAndroid Build Coastguard Worker    make install
322*6236dae4SAndroid Build Coastguard Worker```
323*6236dae4SAndroid Build Coastguard Worker
324*6236dae4SAndroid Build Coastguard WorkerThen:
325*6236dae4SAndroid Build Coastguard Worker
326*6236dae4SAndroid Build Coastguard Worker```bash
327*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
328*6236dae4SAndroid Build Coastguard Worker    git clone https://github.com/curl/curl
329*6236dae4SAndroid Build Coastguard Worker    cd curl
330*6236dae4SAndroid Build Coastguard Worker    autoreconf -fi
331*6236dae4SAndroid Build Coastguard Worker    LDFLAGS="-Wl,-rpath,$HOME/code/boringssl/inst/lib" ./configure --with-ssl=$HOME/code/boringssl/inst --enable-ech --enable-httpsrr
332*6236dae4SAndroid Build Coastguard Worker    ...lots of output...
333*6236dae4SAndroid Build Coastguard Worker    WARNING: ECH HTTPSRR enabled but marked EXPERIMENTAL. Use with caution.
334*6236dae4SAndroid Build Coastguard Worker    make
335*6236dae4SAndroid Build Coastguard Worker```
336*6236dae4SAndroid Build Coastguard Worker
337*6236dae4SAndroid Build Coastguard WorkerThe BoringSSL APIs are fairly similar to those in our ECH-enabled OpenSSL
338*6236dae4SAndroid Build Coastguard Workerfork, so code changes are also in ``lib/vtls/openssl.c``, protected
339*6236dae4SAndroid Build Coastguard Workervia ``#ifdef OPENSSL_IS_BORINGSSL`` and are mostly obvious API variations.
340*6236dae4SAndroid Build Coastguard Worker
341*6236dae4SAndroid Build Coastguard WorkerThe BoringSSL APIs however do not support the ``--ech pn:`` command line
342*6236dae4SAndroid Build Coastguard Workervariant as of now.
343*6236dae4SAndroid Build Coastguard Worker
344*6236dae4SAndroid Build Coastguard Worker## wolfSSL build
345*6236dae4SAndroid Build Coastguard Worker
346*6236dae4SAndroid Build Coastguard WorkerwolfSSL also supports ECH and can be used by curl, so here's how:
347*6236dae4SAndroid Build Coastguard Worker
348*6236dae4SAndroid Build Coastguard Worker```bash
349*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
350*6236dae4SAndroid Build Coastguard Worker    git clone https://github.com/wolfSSL/wolfssl
351*6236dae4SAndroid Build Coastguard Worker    cd wolfssl
352*6236dae4SAndroid Build Coastguard Worker    ./autogen.sh
353*6236dae4SAndroid Build Coastguard Worker    ./configure --prefix=$HOME/code/wolfssl/inst --enable-ech --enable-debug --enable-opensslextra
354*6236dae4SAndroid Build Coastguard Worker    make
355*6236dae4SAndroid Build Coastguard Worker    make install
356*6236dae4SAndroid Build Coastguard Worker```
357*6236dae4SAndroid Build Coastguard Worker
358*6236dae4SAndroid Build Coastguard WorkerThe install prefix (``inst``) in the above causes wolfSSL to be installed there
359*6236dae4SAndroid Build Coastguard Workerand we seem to need that for the curl configure command to work out. The
360*6236dae4SAndroid Build Coastguard Worker``--enable-opensslextra`` turns out (after much faffing about;-) to be
361*6236dae4SAndroid Build Coastguard Workerimportant or else we get build problems with curl below.
362*6236dae4SAndroid Build Coastguard Worker
363*6236dae4SAndroid Build Coastguard Worker```bash
364*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code
365*6236dae4SAndroid Build Coastguard Worker    git clone https://github.com/curl/curl
366*6236dae4SAndroid Build Coastguard Worker    cd curl
367*6236dae4SAndroid Build Coastguard Worker    autoreconf -fi
368*6236dae4SAndroid Build Coastguard Worker    ./configure --with-wolfssl=$HOME/code/wolfssl/inst --enable-ech --enable-httpsrr
369*6236dae4SAndroid Build Coastguard Worker    make
370*6236dae4SAndroid Build Coastguard Worker```
371*6236dae4SAndroid Build Coastguard Worker
372*6236dae4SAndroid Build Coastguard WorkerThere are some known issues with the ECH implementation in wolfSSL:
373*6236dae4SAndroid Build Coastguard Worker
374*6236dae4SAndroid Build Coastguard Worker- The main issue is that the client currently handles HelloRetryRequest
375*6236dae4SAndroid Build Coastguard Worker  incorrectly.  [HRR issue](https://github.com/wolfSSL/wolfssl/issues/6802).)
376*6236dae4SAndroid Build Coastguard Worker  The HRR issue means that the client does not work for
377*6236dae4SAndroid Build Coastguard Worker  [this ECH test web site](https://tls-ech.dev) and any other similarly configured
378*6236dae4SAndroid Build Coastguard Worker  sites.
379*6236dae4SAndroid Build Coastguard Worker- There is also an issue related to so-called middlebox compatibility mode.
380*6236dae4SAndroid Build Coastguard Worker  [middlebox compatibility issue](https://github.com/wolfSSL/wolfssl/issues/6774)
381*6236dae4SAndroid Build Coastguard Worker
382*6236dae4SAndroid Build Coastguard Worker### Code changes to support wolfSSL
383*6236dae4SAndroid Build Coastguard Worker
384*6236dae4SAndroid Build Coastguard WorkerThere are what seem like oddball differences:
385*6236dae4SAndroid Build Coastguard Worker
386*6236dae4SAndroid Build Coastguard Worker- The DoH URL in``$HOME/.curlrc`` can use `1.1.1.1` for OpenSSL but has to be
387*6236dae4SAndroid Build Coastguard Worker  `one.one.one.one` for wolfSSL. The latter works for both, so OK, we us that.
388*6236dae4SAndroid Build Coastguard Worker- There seems to be some difference in CA databases too - the wolfSSL version
389*6236dae4SAndroid Build Coastguard Worker  does not like ``defo.ie``, whereas the system and OpenSSL ones do. We can
390*6236dae4SAndroid Build Coastguard Worker  ignore that for our purposes via ``--insecure``/``-k`` but would need to fix
391*6236dae4SAndroid Build Coastguard Worker  for a real setup. (Browsers do like those certificates though.)
392*6236dae4SAndroid Build Coastguard Worker
393*6236dae4SAndroid Build Coastguard WorkerThen there are some functional code changes:
394*6236dae4SAndroid Build Coastguard Worker
395*6236dae4SAndroid Build Coastguard Worker- tweak to ``configure.ac`` to check if wolfSSL has ECH or not
396*6236dae4SAndroid Build Coastguard Worker- added code to ``lib/vtls/wolfssl.c`` mirroring what's done in the
397*6236dae4SAndroid Build Coastguard Worker  OpenSSL equivalent above.
398*6236dae4SAndroid Build Coastguard Worker- wolfSSL does not support ``--ech false`` or the ``--ech pn:`` command line
399*6236dae4SAndroid Build Coastguard Worker  argument.
400*6236dae4SAndroid Build Coastguard Worker
401*6236dae4SAndroid Build Coastguard WorkerThe lack of support for ``--ech false`` is because wolfSSL has decided to
402*6236dae4SAndroid Build Coastguard Workeralways at least GREASE if built to support ECH. In other words, GREASE is
403*6236dae4SAndroid Build Coastguard Workera compile time choice for wolfSSL, but a runtime choice for OpenSSL or
404*6236dae4SAndroid Build Coastguard WorkerBoringSSL. (Both are reasonable.)
405*6236dae4SAndroid Build Coastguard Worker
406*6236dae4SAndroid Build Coastguard Worker## Additional notes
407*6236dae4SAndroid Build Coastguard Worker
408*6236dae4SAndroid Build Coastguard Worker### Supporting ECH without DoH
409*6236dae4SAndroid Build Coastguard Worker
410*6236dae4SAndroid Build Coastguard WorkerAll of the above only applies if DoH is being used. There should be a use-case
411*6236dae4SAndroid Build Coastguard Workerfor ECH when DoH is not used by curl - if a system stub resolver supports DoT
412*6236dae4SAndroid Build Coastguard Workeror DoH, then, considering only ECH and the network threat model, it would make
413*6236dae4SAndroid Build Coastguard Workersense for curl to support ECH without curl itself using DoH. The author for
414*6236dae4SAndroid Build Coastguard Workerexample uses a combination of stubby+unbound as the system resolver listening
415*6236dae4SAndroid Build Coastguard Workeron localhost:53, so would fit this use-case. That said, it is unclear if
416*6236dae4SAndroid Build Coastguard Workerthis is a niche that is worth trying to address. (The author is just as happy to
417*6236dae4SAndroid Build Coastguard Workerlet curl use DoH to talk to the same public recursive that stubby might use:-)
418*6236dae4SAndroid Build Coastguard Worker
419*6236dae4SAndroid Build Coastguard WorkerAssuming for the moment this is a use-case we would like to support, then if
420*6236dae4SAndroid Build Coastguard WorkerDoH is not being used by curl, it is not clear at this time how to provide
421*6236dae4SAndroid Build Coastguard Workersupport for ECH. One option would seem to be to extend the ``c-ares`` library
422*6236dae4SAndroid Build Coastguard Workerto support HTTPS RRs, but in that case it is not now clear whether such
423*6236dae4SAndroid Build Coastguard Workerchanges would be attractive to the ``c-ares`` maintainers, nor whether the
424*6236dae4SAndroid Build Coastguard Worker"tag=value" extensibility inherent in the HTTPS/SVCB specification is a good
425*6236dae4SAndroid Build Coastguard Workermatch for the ``c-ares`` approach of defining structures specific to decoded
426*6236dae4SAndroid Build Coastguard Workeranswers for each supported RRtype. We are also not sure how many downstream
427*6236dae4SAndroid Build Coastguard Workercurl deployments actually make use of the ``c-ares`` library, which would
428*6236dae4SAndroid Build Coastguard Workeraffect the utility of such changes. Another option might be to consider using
429*6236dae4SAndroid Build Coastguard Workersome other generic DNS library that does support HTTPS RRs, but it is unclear
430*6236dae4SAndroid Build Coastguard Workerif such a library could or would be used by all or almost all curl builds and
431*6236dae4SAndroid Build Coastguard Workerdownstream releases of curl.
432*6236dae4SAndroid Build Coastguard Worker
433*6236dae4SAndroid Build Coastguard WorkerOur current conclusion is that doing the above is likely best left until we
434*6236dae4SAndroid Build Coastguard Workerhave some experience with the "using DoH" approach, so we are going to punt on
435*6236dae4SAndroid Build Coastguard Workerthis for now.
436*6236dae4SAndroid Build Coastguard Worker
437*6236dae4SAndroid Build Coastguard Worker### Debugging
438*6236dae4SAndroid Build Coastguard Worker
439*6236dae4SAndroid Build Coastguard WorkerJust a note to self as remembering this is a nuisance:
440*6236dae4SAndroid Build Coastguard Worker
441*6236dae4SAndroid Build Coastguard Worker```bash
442*6236dae4SAndroid Build Coastguard WorkerLD_LIBRARY_PATH=$HOME/code/openssl:./lib/.libs gdb ./src/.libs/curl
443*6236dae4SAndroid Build Coastguard Worker```
444*6236dae4SAndroid Build Coastguard Worker
445*6236dae4SAndroid Build Coastguard Worker### Localhost testing
446*6236dae4SAndroid Build Coastguard Worker
447*6236dae4SAndroid Build Coastguard WorkerIt can be useful to be able to run against a localhost OpenSSL ``s_server``
448*6236dae4SAndroid Build Coastguard Workerfor testing. We have published instructions for such
449*6236dae4SAndroid Build Coastguard Worker[localhost tests](https://github.com/defo-project/ech-dev-utils/blob/main/howtos/localhost-tests.md)
450*6236dae4SAndroid Build Coastguard Workerin another repository. Once you have that set up, you can start a server
451*6236dae4SAndroid Build Coastguard Workerand then run curl against that:
452*6236dae4SAndroid Build Coastguard Worker
453*6236dae4SAndroid Build Coastguard Worker```bash
454*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code/ech-dev-utils
455*6236dae4SAndroid Build Coastguard Worker    ./scripts/echsvr.sh -d
456*6236dae4SAndroid Build Coastguard Worker    ...
457*6236dae4SAndroid Build Coastguard Worker```
458*6236dae4SAndroid Build Coastguard Worker
459*6236dae4SAndroid Build Coastguard WorkerThe ``echsvr.sh`` script supports many ECH-related options. Use ``echsvr.sh -h``
460*6236dae4SAndroid Build Coastguard Workerfor details.
461*6236dae4SAndroid Build Coastguard Worker
462*6236dae4SAndroid Build Coastguard WorkerIn another window:
463*6236dae4SAndroid Build Coastguard Worker
464*6236dae4SAndroid Build Coastguard Worker```bash
465*6236dae4SAndroid Build Coastguard Worker    cd $HOME/code/curl/
466*6236dae4SAndroid Build Coastguard Worker    ./src/curl -vvv --insecure  --connect-to foo.example.com:8443:localhost:8443  --ech ecl:AD7+DQA6uwAgACBix2B78sX+EQhEbxMspDOc8Z3xVS5aQpYP0Cxpc2AWPAAEAAEAAQALZXhhbXBsZS5jb20AAA==
467*6236dae4SAndroid Build Coastguard Worker```
468*6236dae4SAndroid Build Coastguard Worker
469*6236dae4SAndroid Build Coastguard Worker### Automated use of ``retry_configs`` not supported so far...
470*6236dae4SAndroid Build Coastguard Worker
471*6236dae4SAndroid Build Coastguard WorkerAs of now we have not added support for using ``retry_config`` handling in the
472*6236dae4SAndroid Build Coastguard Workerapplication - for a command line tool, one can just use ``dig`` (or ``kdig``)
473*6236dae4SAndroid Build Coastguard Workerto get the HTTPS RR and pass the ECHConfigList from that on the command line,
474*6236dae4SAndroid Build Coastguard Workerif needed, or one can access the value from command line output in verbose more
475*6236dae4SAndroid Build Coastguard Workerand then reuse that in another invocation.
476*6236dae4SAndroid Build Coastguard Worker
477*6236dae4SAndroid Build Coastguard WorkerBoth our OpenSSL fork and BoringSSL have APIs for both controlling GREASE and
478*6236dae4SAndroid Build Coastguard Workeraccessing and logging ``retry_configs``, it seems wolfSSL has neither.
479