/src/openssl/ssl/ech/ech_internal.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #include <openssl/ssl.h> |
11 | | #include <openssl/ech.h> |
12 | | #include <openssl/rand.h> |
13 | | #include <openssl/kdf.h> |
14 | | #include "internal/ech_helpers.h" |
15 | | #include "internal/ssl_unwrap.h" |
16 | | #include "../ssl_local.h" |
17 | | #include "../statem/statem_local.h" |
18 | | #include "ech_local.h" |
19 | | |
20 | | #ifndef OPENSSL_NO_ECH |
21 | | |
22 | | /* |
23 | | * Strings used in ECH crypto derivations (odd format for EBCDIC goodness) |
24 | | */ |
25 | | /* "ech accept confirmation" */ |
26 | | static const char OSSL_ECH_ACCEPT_CONFIRM_STRING[] = "\x65\x63\x68\x20\x61\x63\x63\x65\x70\x74\x20\x63\x6f\x6e\x66\x69\x72\x6d\x61\x74\x69\x6f\x6e"; |
27 | | /* "hrr ech accept confirmation" */ |
28 | | static const char OSSL_ECH_HRR_CONFIRM_STRING[] = "\x68\x72\x72\x20\x65\x63\x68\x20\x61\x63\x63\x65\x70\x74\x20\x63\x6f\x6e\x66\x69\x72\x6d\x61\x74\x69\x6f\x6e"; |
29 | | |
30 | | /* ECH internal API functions */ |
31 | | |
32 | | #ifdef OSSL_ECH_SUPERVERBOSE |
33 | | /* ascii-hex print a buffer nicely for debug/interop purposes */ |
34 | | void ossl_ech_pbuf(const char *msg, const unsigned char *buf, const size_t blen) |
35 | 0 | { |
36 | 0 | OSSL_TRACE_BEGIN(TLS) |
37 | 0 | { |
38 | 0 | if (msg == NULL) { |
39 | 0 | BIO_printf(trc_out, "msg is NULL\n"); |
40 | 0 | } else if (buf == NULL || blen == 0) { |
41 | 0 | BIO_printf(trc_out, "%s: buf is %p\n", msg, (void *)buf); |
42 | 0 | BIO_printf(trc_out, "%s: blen is %lu\n", msg, (unsigned long)blen); |
43 | 0 | } else { |
44 | 0 | BIO_printf(trc_out, "%s (%lu)\n", msg, (unsigned long)blen); |
45 | 0 | BIO_dump_indent(trc_out, buf, (int)blen, 4); |
46 | 0 | } |
47 | 0 | } |
48 | 0 | OSSL_TRACE_END(TLS); |
49 | 0 | return; |
50 | 0 | } |
51 | | |
52 | | /* trace out transcript */ |
53 | | static void ossl_ech_ptranscript(SSL_CONNECTION *s, const char *msg) |
54 | 0 | { |
55 | 0 | size_t hdatalen = 0; |
56 | 0 | unsigned char *hdata = NULL; |
57 | 0 | unsigned char ddata[EVP_MAX_MD_SIZE]; |
58 | 0 | size_t ddatalen; |
59 | |
|
60 | 0 | if (s == NULL) |
61 | 0 | return; |
62 | 0 | hdatalen = BIO_get_mem_data(s->s3.handshake_buffer, &hdata); |
63 | 0 | ossl_ech_pbuf(msg, hdata, hdatalen); |
64 | 0 | if (s->s3.handshake_dgst != NULL) { |
65 | 0 | if (ssl_handshake_hash(s, ddata, sizeof(ddata), &ddatalen) == 0) { |
66 | 0 | OSSL_TRACE(TLS, "ssl_handshake_hash failed\n"); |
67 | 0 | ossl_ech_pbuf(msg, ddata, ddatalen); |
68 | 0 | } |
69 | 0 | } |
70 | 0 | OSSL_TRACE(TLS, "new transbuf:\n"); |
71 | 0 | ossl_ech_pbuf(msg, s->ext.ech.transbuf, s->ext.ech.transbuf_len); |
72 | 0 | return; |
73 | 0 | } |
74 | | #endif |
75 | | |
76 | | static OSSL_ECHSTORE_ENTRY *ossl_echstore_entry_dup(const OSSL_ECHSTORE_ENTRY *orig) |
77 | 0 | { |
78 | 0 | OSSL_ECHSTORE_ENTRY *ret = NULL; |
79 | |
|
80 | 0 | if (orig == NULL) |
81 | 0 | return NULL; |
82 | 0 | ret = OPENSSL_zalloc(sizeof(*ret)); |
83 | 0 | if (ret == NULL) |
84 | 0 | return NULL; |
85 | 0 | ret->version = orig->version; |
86 | 0 | if (orig->public_name != NULL) { |
87 | 0 | ret->public_name = OPENSSL_strdup(orig->public_name); |
88 | 0 | if (ret->public_name == NULL) |
89 | 0 | goto err; |
90 | 0 | } |
91 | 0 | ret->pub_len = orig->pub_len; |
92 | 0 | if (orig->pub != NULL) { |
93 | 0 | ret->pub = OPENSSL_memdup(orig->pub, orig->pub_len); |
94 | 0 | if (ret->pub == NULL) |
95 | 0 | goto err; |
96 | 0 | } |
97 | 0 | ret->nsuites = orig->nsuites; |
98 | 0 | ret->suites = OPENSSL_memdup(orig->suites, sizeof(OSSL_HPKE_SUITE) * ret->nsuites); |
99 | 0 | if (ret->suites == NULL) |
100 | 0 | goto err; |
101 | 0 | ret->max_name_length = orig->max_name_length; |
102 | 0 | ret->config_id = orig->config_id; |
103 | 0 | if (orig->exts != NULL) { |
104 | 0 | ret->exts = sk_OSSL_ECHEXT_deep_copy(orig->exts, ossl_echext_dup, |
105 | 0 | ossl_echext_free); |
106 | 0 | if (ret->exts == NULL) |
107 | 0 | goto err; |
108 | 0 | } |
109 | 0 | ret->loadtime = orig->loadtime; |
110 | 0 | if (orig->keyshare != NULL) { |
111 | 0 | if (!EVP_PKEY_up_ref(orig->keyshare)) |
112 | 0 | goto err; |
113 | 0 | ret->keyshare = orig->keyshare; |
114 | 0 | } |
115 | 0 | ret->for_retry = orig->for_retry; |
116 | 0 | if (orig->encoded != NULL) { |
117 | 0 | ret->encoded_len = orig->encoded_len; |
118 | 0 | ret->encoded = OPENSSL_memdup(orig->encoded, ret->encoded_len); |
119 | 0 | if (ret->encoded == NULL) |
120 | 0 | goto err; |
121 | 0 | } |
122 | 0 | return ret; |
123 | 0 | err: |
124 | 0 | ossl_echstore_entry_free(ret); |
125 | 0 | return NULL; |
126 | 0 | } |
127 | | |
128 | | /* duplicate an OSSL_ECHSTORE as needed */ |
129 | | OSSL_ECHSTORE *ossl_echstore_dup(const OSSL_ECHSTORE *old) |
130 | 0 | { |
131 | 0 | OSSL_ECHSTORE *cp = NULL; |
132 | |
|
133 | 0 | if (old == NULL) |
134 | 0 | return NULL; |
135 | 0 | cp = OPENSSL_zalloc(sizeof(*cp)); |
136 | 0 | if (cp == NULL) |
137 | 0 | return NULL; |
138 | 0 | cp->libctx = old->libctx; |
139 | 0 | if (old->propq != NULL) { |
140 | 0 | cp->propq = OPENSSL_strdup(old->propq); |
141 | 0 | if (cp->propq == NULL) |
142 | 0 | goto err; |
143 | 0 | } |
144 | 0 | if (old->entries != NULL) { |
145 | 0 | cp->entries = sk_OSSL_ECHSTORE_ENTRY_deep_copy(old->entries, |
146 | 0 | ossl_echstore_entry_dup, |
147 | 0 | ossl_echstore_entry_free); |
148 | 0 | if (cp->entries == NULL) |
149 | 0 | goto err; |
150 | 0 | } |
151 | 0 | return cp; |
152 | 0 | err: |
153 | 0 | OSSL_ECHSTORE_free(cp); |
154 | 0 | return NULL; |
155 | 0 | } |
156 | | |
157 | | void ossl_ech_ctx_clear(OSSL_ECH_CTX *ce) |
158 | 0 | { |
159 | 0 | if (ce == NULL) |
160 | 0 | return; |
161 | 0 | OSSL_ECHSTORE_free(ce->es); |
162 | 0 | OPENSSL_free(ce->alpn_outer); |
163 | 0 | return; |
164 | 0 | } |
165 | | |
166 | | static void ech_free_stashed_key_shares(OSSL_ECH_CONN *ec) |
167 | 0 | { |
168 | 0 | size_t i; |
169 | |
|
170 | 0 | if (ec == NULL) |
171 | 0 | return; |
172 | 0 | for (i = 0; i != ec->num_ks_pkey; i++) { |
173 | 0 | EVP_PKEY_free(ec->ks_pkey[i]); |
174 | 0 | ec->ks_pkey[i] = NULL; |
175 | 0 | } |
176 | 0 | ec->num_ks_pkey = 0; |
177 | 0 | return; |
178 | 0 | } |
179 | | |
180 | | void ossl_ech_conn_clear(OSSL_ECH_CONN *ec) |
181 | 0 | { |
182 | 0 | if (ec == NULL) |
183 | 0 | return; |
184 | 0 | OSSL_ECHSTORE_free(ec->es); |
185 | 0 | OPENSSL_free(ec->outer_hostname); |
186 | 0 | OPENSSL_free(ec->alpn_outer); |
187 | 0 | OPENSSL_free(ec->former_inner); |
188 | 0 | OPENSSL_free(ec->transbuf); |
189 | 0 | OPENSSL_free(ec->innerch); |
190 | 0 | OPENSSL_free(ec->grease_suite); |
191 | 0 | OPENSSL_free(ec->sent); |
192 | 0 | OPENSSL_free(ec->returned); |
193 | 0 | OPENSSL_free(ec->pub); |
194 | 0 | OSSL_HPKE_CTX_free(ec->hpke_ctx); |
195 | 0 | OPENSSL_free(ec->encoded_inner); |
196 | 0 | ech_free_stashed_key_shares(ec); |
197 | 0 | return; |
198 | 0 | } |
199 | | |
200 | | /* called from ssl/ssl_lib.c: ossl_ssl_connection_new_int */ |
201 | | int ossl_ech_conn_init(SSL_CONNECTION *s, SSL_CTX *ctx, |
202 | | const SSL_METHOD *method) |
203 | 0 | { |
204 | 0 | memset(&s->ext.ech, 0, sizeof(s->ext.ech)); |
205 | 0 | if (ctx->ext.ech.es != NULL |
206 | 0 | && (s->ext.ech.es = ossl_echstore_dup(ctx->ext.ech.es)) == NULL) |
207 | 0 | goto err; |
208 | 0 | s->ext.ech.cb = ctx->ext.ech.cb; |
209 | 0 | if (ctx->ext.ech.alpn_outer != NULL) { |
210 | 0 | s->ext.ech.alpn_outer = OPENSSL_memdup(ctx->ext.ech.alpn_outer, |
211 | 0 | ctx->ext.ech.alpn_outer_len); |
212 | 0 | if (s->ext.ech.alpn_outer == NULL) |
213 | 0 | goto err; |
214 | 0 | s->ext.ech.alpn_outer_len = ctx->ext.ech.alpn_outer_len; |
215 | 0 | } |
216 | | /* initialise type/cid to unknown */ |
217 | 0 | s->ext.ech.attempted_type = OSSL_ECH_type_unknown; |
218 | 0 | s->ext.ech.attempted_cid = OSSL_ECH_config_id_unset; |
219 | 0 | if (s->ext.ech.es != NULL) |
220 | 0 | s->ext.ech.attempted = 1; |
221 | 0 | if ((ctx->options & SSL_OP_ECH_GREASE) != 0) |
222 | 0 | s->options |= SSL_OP_ECH_GREASE; |
223 | 0 | return 1; |
224 | 0 | err: |
225 | 0 | OSSL_ECHSTORE_free(s->ext.ech.es); |
226 | 0 | s->ext.ech.es = NULL; |
227 | 0 | OPENSSL_free(s->ext.ech.alpn_outer); |
228 | 0 | s->ext.ech.alpn_outer = NULL; |
229 | 0 | s->ext.ech.alpn_outer_len = 0; |
230 | 0 | return 0; |
231 | 0 | } |
232 | | |
233 | | /* |
234 | | * Assemble the set of ECHConfig values to return as retry-configs. |
235 | | * The caller (stoc ECH extension handler) needs to OPENSSL_free the rcfgs |
236 | | * The rcfgs itself is missing the outer length to make it an ECHConfigList |
237 | | * so the caller adds that using WPACKET functions |
238 | | */ |
239 | | int ossl_ech_get_retry_configs(SSL_CONNECTION *s, unsigned char **rcfgs, |
240 | | size_t *rcfgslen) |
241 | 0 | { |
242 | 0 | OSSL_ECHSTORE *es = NULL; |
243 | 0 | OSSL_ECHSTORE_ENTRY *ee = NULL; |
244 | 0 | int i, num = 0; |
245 | 0 | size_t retslen = 0; |
246 | 0 | unsigned char *tmp = NULL, *rets = NULL; |
247 | |
|
248 | 0 | if (s == NULL || rcfgs == NULL || rcfgslen == NULL) |
249 | 0 | return 0; |
250 | 0 | es = s->ext.ech.es; |
251 | 0 | if (es != NULL && es->entries != NULL) |
252 | 0 | num = sk_OSSL_ECHSTORE_ENTRY_num(es->entries); |
253 | 0 | for (i = 0; i != num; i++) { |
254 | 0 | ee = sk_OSSL_ECHSTORE_ENTRY_value(es->entries, i); |
255 | 0 | if (ee != NULL && ee->for_retry == OSSL_ECH_FOR_RETRY) { |
256 | 0 | if (ee->encoded_len > SIZE_MAX - retslen) |
257 | 0 | goto err; |
258 | 0 | tmp = (unsigned char *)OPENSSL_realloc(rets, |
259 | 0 | retslen + ee->encoded_len); |
260 | 0 | if (tmp == NULL) |
261 | 0 | goto err; |
262 | 0 | rets = tmp; |
263 | 0 | memcpy(rets + retslen, ee->encoded, ee->encoded_len); |
264 | 0 | retslen += ee->encoded_len; |
265 | 0 | } |
266 | 0 | } |
267 | 0 | *rcfgs = rets; |
268 | 0 | *rcfgslen = retslen; |
269 | 0 | return 1; |
270 | 0 | err: |
271 | 0 | OPENSSL_free(rets); |
272 | 0 | *rcfgs = NULL; |
273 | 0 | *rcfgslen = 0; |
274 | 0 | return 0; |
275 | 0 | } |
276 | | |
277 | | /* GREASEy constants */ |
278 | 0 | #define OSSL_ECH_MAX_GREASE_PUB 0x100 /* buffer size for 'enc' values */ |
279 | | #define OSSL_ECH_MAX_GREASE_CT 0x200 /* max GREASEy ciphertext we'll emit */ |
280 | | |
281 | | /* |
282 | | * Send a random value that looks like a real ECH. |
283 | | * |
284 | | * We do GREASEing as follows: |
285 | | * - always HKDF-SHA256 |
286 | | * - always AES-128-GCM |
287 | | * - random config ID, even for requests to same server in same session |
288 | | * - random enc |
289 | | * - random looking payload, randomly 144, 176, 208, 240 bytes, no correlation with server |
290 | | */ |
291 | | int ossl_ech_send_grease(SSL_CONNECTION *s, WPACKET *pkt) |
292 | 0 | { |
293 | 0 | OSSL_HPKE_SUITE hpke_suite_in = OSSL_HPKE_SUITE_DEFAULT; |
294 | 0 | OSSL_HPKE_SUITE *hpke_suite_in_p = NULL; |
295 | 0 | OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; |
296 | 0 | size_t pp_at_start = 0, pp_at_end = 0; |
297 | 0 | size_t senderpub_len = OSSL_ECH_MAX_GREASE_PUB; |
298 | 0 | size_t cipher_len = 0, cipher_len_jitter = 0; |
299 | 0 | unsigned char cid, senderpub[OSSL_ECH_MAX_GREASE_PUB]; |
300 | 0 | unsigned char cipher[OSSL_ECH_MAX_GREASE_CT]; |
301 | 0 | SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); |
302 | |
|
303 | 0 | if (!WPACKET_get_total_written(pkt, &pp_at_start)) { |
304 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
305 | 0 | return 0; |
306 | 0 | } |
307 | | /* randomly select cipher_len to be one of 144, 176, 208, 244 */ |
308 | 0 | if (RAND_bytes_ex(sctx->libctx, &cid, 1, 0) <= 0) { |
309 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
310 | 0 | return 0; |
311 | 0 | } |
312 | 0 | cipher_len_jitter = cid % 4; |
313 | 0 | cipher_len = 144; |
314 | 0 | cipher_len += 32 * cipher_len_jitter; |
315 | | /* generate a random (1 octet) client id */ |
316 | 0 | if (RAND_bytes_ex(sctx->libctx, &cid, 1, 0) <= 0) { |
317 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
318 | 0 | return 0; |
319 | 0 | } |
320 | 0 | s->ext.ech.attempted_cid = cid; |
321 | 0 | hpke_suite_in_p = &hpke_suite; |
322 | 0 | if (s->ext.ech.grease_suite != NULL) { |
323 | 0 | if (OSSL_HPKE_str2suite(s->ext.ech.grease_suite, &hpke_suite_in) != 1) { |
324 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
325 | 0 | return 0; |
326 | 0 | } |
327 | 0 | hpke_suite_in_p = &hpke_suite_in; |
328 | 0 | } |
329 | 0 | if (OSSL_HPKE_get_grease_value(hpke_suite_in_p, &hpke_suite, |
330 | 0 | senderpub, &senderpub_len, |
331 | 0 | cipher, cipher_len, |
332 | 0 | sctx->libctx, sctx->propq) |
333 | 0 | != 1) { |
334 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
335 | 0 | return 0; |
336 | 0 | } |
337 | 0 | if (!WPACKET_put_bytes_u16(pkt, s->ext.ech.attempted_type) |
338 | 0 | || !WPACKET_start_sub_packet_u16(pkt) |
339 | 0 | || !WPACKET_put_bytes_u8(pkt, OSSL_ECH_OUTER_CH_TYPE) |
340 | 0 | || !WPACKET_put_bytes_u16(pkt, hpke_suite.kdf_id) |
341 | 0 | || !WPACKET_put_bytes_u16(pkt, hpke_suite.aead_id) |
342 | 0 | || !WPACKET_put_bytes_u8(pkt, cid) |
343 | 0 | || !WPACKET_sub_memcpy_u16(pkt, senderpub, senderpub_len) |
344 | 0 | || !WPACKET_sub_memcpy_u16(pkt, cipher, cipher_len) |
345 | 0 | || !WPACKET_close(pkt)) { |
346 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
347 | 0 | return 0; |
348 | 0 | } |
349 | | /* record the ECH sent so we can re-tx same if we hit an HRR */ |
350 | 0 | OPENSSL_free(s->ext.ech.sent); |
351 | 0 | if (!WPACKET_get_total_written(pkt, &pp_at_end)) { |
352 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
353 | 0 | return 0; |
354 | 0 | } |
355 | 0 | s->ext.ech.sent_len = pp_at_end - pp_at_start; |
356 | 0 | s->ext.ech.sent = OPENSSL_malloc(s->ext.ech.sent_len); |
357 | 0 | if (s->ext.ech.sent == NULL) { |
358 | 0 | s->ext.ech.sent_len = 0; |
359 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
360 | 0 | return 0; |
361 | 0 | } |
362 | 0 | memcpy(s->ext.ech.sent, WPACKET_get_curr(pkt) - s->ext.ech.sent_len, |
363 | 0 | s->ext.ech.sent_len); |
364 | 0 | s->ext.ech.grease = OSSL_ECH_IS_GREASE; |
365 | 0 | OSSL_TRACE_BEGIN(TLS) |
366 | 0 | { |
367 | 0 | BIO_printf(trc_out, "ECH - sending GREASE\n"); |
368 | 0 | } |
369 | 0 | OSSL_TRACE_END(TLS); |
370 | 0 | return 1; |
371 | 0 | } |
372 | | |
373 | | /* |
374 | | * Search the ECH store for one that's a match. If no outer_name was set via |
375 | | * API then we just take the 1st match where we locally support the HPKE suite. |
376 | | * If OTOH, an outer_name was provided via API then we prefer the first that |
377 | | * matches that. Name comparison is via case-insensitive exact matches. |
378 | | */ |
379 | | int ossl_ech_pick_matching_cfg(SSL_CONNECTION *s, OSSL_ECHSTORE_ENTRY **ee, |
380 | | OSSL_HPKE_SUITE *suite) |
381 | 0 | { |
382 | 0 | int namematch = 0, nameoverride = 0, suitematch = 0, num, cind = 0; |
383 | 0 | unsigned int csuite = 0, tsuite = 0; |
384 | 0 | size_t hnlen = 0; |
385 | 0 | OSSL_ECHSTORE_ENTRY *lee = NULL, *tee = NULL; |
386 | 0 | OSSL_ECHSTORE *es = NULL; |
387 | 0 | char *hn = NULL; |
388 | |
|
389 | 0 | if (s == NULL || s->ext.ech.es == NULL || ee == NULL || suite == NULL) |
390 | 0 | return 0; |
391 | 0 | *ee = NULL; |
392 | 0 | es = s->ext.ech.es; |
393 | 0 | if (es->entries == NULL) |
394 | 0 | return 0; |
395 | 0 | num = sk_OSSL_ECHSTORE_ENTRY_num(es->entries); |
396 | | /* allow API-set pref to override */ |
397 | 0 | hn = s->ext.ech.outer_hostname; |
398 | 0 | hnlen = (hn == NULL ? 0 : (unsigned int)strlen(hn)); |
399 | 0 | if (hnlen != 0) |
400 | 0 | nameoverride = 1; |
401 | 0 | if (s->ext.ech.no_outer == 1) { |
402 | 0 | hn = NULL; |
403 | 0 | hnlen = 0; |
404 | 0 | nameoverride = 1; |
405 | 0 | } |
406 | 0 | for (cind = 0; cind < num && (suitematch == 0 || namematch == 0); cind++) { |
407 | 0 | lee = sk_OSSL_ECHSTORE_ENTRY_value(es->entries, cind); |
408 | 0 | if (lee == NULL || lee->version != OSSL_ECH_RFC9849_VERSION) |
409 | 0 | continue; |
410 | 0 | if (nameoverride == 1 && hnlen == 0) { |
411 | 0 | namematch = 1; |
412 | 0 | } else { |
413 | 0 | namematch = 0; |
414 | 0 | if (hnlen == 0 |
415 | 0 | || (lee->public_name != NULL |
416 | 0 | && strlen(lee->public_name) == hnlen |
417 | 0 | && OPENSSL_strncasecmp(hn, (char *)lee->public_name, |
418 | 0 | hnlen) |
419 | 0 | == 0)) |
420 | 0 | namematch = 1; |
421 | 0 | } |
422 | 0 | suitematch = 0; |
423 | 0 | for (csuite = 0; csuite != lee->nsuites && suitematch == 0; csuite++) { |
424 | 0 | if (OSSL_HPKE_suite_check(lee->suites[csuite]) == 1) { |
425 | 0 | if (tee == NULL) { /* remember 1st suite match for override */ |
426 | 0 | tee = lee; |
427 | 0 | tsuite = csuite; |
428 | 0 | } |
429 | 0 | suitematch = 1; |
430 | 0 | if (namematch == 1) { /* pick this one if both "fit" */ |
431 | 0 | *suite = lee->suites[csuite]; |
432 | 0 | *ee = lee; |
433 | 0 | break; |
434 | 0 | } |
435 | 0 | } |
436 | 0 | } |
437 | 0 | } |
438 | 0 | if (tee != NULL && nameoverride == 1 |
439 | 0 | && (namematch == 0 || suitematch == 0)) { |
440 | 0 | *suite = tee->suites[tsuite]; |
441 | 0 | *ee = tee; |
442 | 0 | } else if (namematch == 0 || suitematch == 0) { |
443 | | /* no joy */ |
444 | 0 | return 0; |
445 | 0 | } |
446 | 0 | if (*ee == NULL || (*ee)->pub_len == 0 || (*ee)->pub == NULL) |
447 | 0 | return 0; |
448 | 0 | return 1; |
449 | 0 | } |
450 | | |
451 | | /* Make up the ClientHelloInner and EncodedClientHelloInner buffers */ |
452 | | int ossl_ech_encode_inner(SSL_CONNECTION *s, unsigned char **encoded, |
453 | | size_t *encoded_len) |
454 | 0 | { |
455 | 0 | int rv = 0; |
456 | 0 | size_t nraws = 0, ind = 0, innerlen = 0; |
457 | 0 | WPACKET inner = { 0 }; /* "fake" pkt for inner */ |
458 | 0 | BUF_MEM *inner_mem = NULL; |
459 | 0 | RAW_EXTENSION *raws = NULL; |
460 | | |
461 | | /* basic checks */ |
462 | 0 | if (s == NULL) |
463 | 0 | return 0; |
464 | 0 | if (s->ext.ech.es == NULL || s->clienthello == NULL) { |
465 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
466 | 0 | return 0; |
467 | 0 | } |
468 | 0 | if ((inner_mem = BUF_MEM_new()) == NULL |
469 | 0 | || !WPACKET_init(&inner, inner_mem) |
470 | | /* We don't add the type and 3-octet header as usually done */ |
471 | | /* Add ver/rnd/sess-id/suites to buffer */ |
472 | 0 | || !WPACKET_put_bytes_u16(&inner, s->client_version) |
473 | 0 | || !WPACKET_memcpy(&inner, s->ext.ech.client_random, SSL3_RANDOM_SIZE) |
474 | | /* Session ID is forced to zero in the encoded inner */ |
475 | 0 | || !WPACKET_sub_memcpy_u8(&inner, NULL, 0) |
476 | | /* Ciphers supported */ |
477 | 0 | || !WPACKET_start_sub_packet_u16(&inner) |
478 | 0 | || !ssl_cipher_list_to_bytes(s, SSL_get_ciphers(&s->ssl), &inner) |
479 | 0 | || !WPACKET_close(&inner) |
480 | | /* COMPRESSION */ |
481 | 0 | || !WPACKET_start_sub_packet_u8(&inner) |
482 | | /* Add the NULL compression method */ |
483 | 0 | || !WPACKET_put_bytes_u8(&inner, 0) |
484 | 0 | || !WPACKET_close(&inner)) { |
485 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
486 | 0 | goto err; |
487 | 0 | } |
488 | | /* Now handle extensions */ |
489 | 0 | if (!WPACKET_start_sub_packet_u16(&inner)) { |
490 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
491 | 0 | goto err; |
492 | 0 | } |
493 | | /* Grab a pointer to the already constructed extensions */ |
494 | 0 | raws = s->clienthello->pre_proc_exts; |
495 | 0 | nraws = s->clienthello->pre_proc_exts_len; |
496 | 0 | if (raws == NULL || nraws < TLSEXT_IDX_num_builtins) { |
497 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
498 | 0 | goto err; |
499 | 0 | } |
500 | | /* We put ECH-compressed stuff first (if any), because we can */ |
501 | 0 | if (s->ext.ech.n_outer_only > 0) { |
502 | 0 | if (!WPACKET_put_bytes_u16(&inner, TLSEXT_TYPE_outer_extensions) |
503 | 0 | || !WPACKET_start_sub_packet_u16(&inner) |
504 | | /* redundant encoding of more-or-less the same thing */ |
505 | 0 | || !WPACKET_start_sub_packet_u8(&inner)) { |
506 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
507 | 0 | goto err; |
508 | 0 | } |
509 | | /* add the types for each of the compressed extensions now */ |
510 | 0 | for (ind = 0; ind != s->ext.ech.n_outer_only; ind++) { |
511 | 0 | if (!WPACKET_put_bytes_u16(&inner, s->ext.ech.outer_only[ind])) { |
512 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
513 | 0 | goto err; |
514 | 0 | } |
515 | 0 | } |
516 | | /* close the 2 sub-packets with the compressed types */ |
517 | 0 | if (!WPACKET_close(&inner) || !WPACKET_close(&inner)) { |
518 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
519 | 0 | goto err; |
520 | 0 | } |
521 | 0 | } |
522 | | /* now copy the rest, as "proper" exts, into encoded inner */ |
523 | 0 | for (ind = 0; ind < TLSEXT_IDX_num_builtins; ind++) { |
524 | 0 | if (raws[ind].present == 0 || ossl_ech_2bcompressed((int)ind) == 1) |
525 | 0 | continue; |
526 | 0 | if (!WPACKET_put_bytes_u16(&inner, raws[ind].type) |
527 | 0 | || !WPACKET_sub_memcpy_u16(&inner, PACKET_data(&raws[ind].data), |
528 | 0 | PACKET_remaining(&raws[ind].data))) { |
529 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
530 | 0 | goto err; |
531 | 0 | } |
532 | 0 | } |
533 | 0 | if (!WPACKET_close(&inner) /* close the encoded inner packet */ |
534 | 0 | || !WPACKET_get_length(&inner, &innerlen)) { /* len for inner CH */ |
535 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
536 | 0 | goto err; |
537 | 0 | } |
538 | 0 | *encoded = (unsigned char *)inner_mem->data; |
539 | 0 | inner_mem->data = NULL; /* keep BUF_MEM_free happy */ |
540 | 0 | *encoded_len = innerlen; |
541 | | /* and clean up */ |
542 | 0 | rv = 1; |
543 | 0 | err: |
544 | 0 | WPACKET_cleanup(&inner); |
545 | 0 | BUF_MEM_free(inner_mem); |
546 | 0 | return rv; |
547 | 0 | } |
548 | | |
549 | | /* |
550 | | * Find ECH acceptance signal in a SH |
551 | | * hrr is 1 if this is for an HRR, otherwise for SH |
552 | | * acbuf is (a preallocated) 8 octet buffer |
553 | | * shbuf is a pointer to the SH buffer |
554 | | * shlen is the length of the SH buf |
555 | | * return: 1 for success, 0 otherwise |
556 | | */ |
557 | | int ossl_ech_find_confirm(SSL_CONNECTION *s, int hrr, |
558 | | unsigned char acbuf[OSSL_ECH_SIGNAL_LEN]) |
559 | 0 | { |
560 | 0 | unsigned char *acp = NULL; |
561 | |
|
562 | 0 | if (hrr == 0) { |
563 | 0 | acp = s->s3.server_random + SSL3_RANDOM_SIZE - OSSL_ECH_SIGNAL_LEN; |
564 | 0 | } else { /* was set in extension handler */ |
565 | 0 | if (s->ext.ech.hrrsignal_p == NULL) |
566 | 0 | return 0; |
567 | 0 | acp = s->ext.ech.hrrsignal; |
568 | 0 | } |
569 | 0 | memcpy(acbuf, acp, OSSL_ECH_SIGNAL_LEN); |
570 | 0 | return 1; |
571 | 0 | } |
572 | | |
573 | | /* |
574 | | * reset the handshake buffer for transcript after ECH is good |
575 | | * buf is the data to put into the transcript (inner CH if no HRR) |
576 | | * blen is the length of buf |
577 | | * return 1 for success |
578 | | */ |
579 | | int ossl_ech_reset_hs_buffer(SSL_CONNECTION *s, const unsigned char *buf, |
580 | | size_t blen) |
581 | 0 | { |
582 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
583 | 0 | ossl_ech_pbuf("RESET transcript to", buf, blen); |
584 | 0 | #endif |
585 | 0 | if (s->s3.handshake_buffer != NULL) { |
586 | 0 | if (BIO_reset(s->s3.handshake_buffer) < 0) |
587 | 0 | return 0; |
588 | 0 | } else { |
589 | 0 | s->s3.handshake_buffer = BIO_new(BIO_s_mem()); |
590 | 0 | if (s->s3.handshake_buffer == NULL) |
591 | 0 | return 0; |
592 | 0 | (void)BIO_set_close(s->s3.handshake_buffer, BIO_CLOSE); |
593 | 0 | } |
594 | 0 | EVP_MD_CTX_free(s->s3.handshake_dgst); |
595 | 0 | s->s3.handshake_dgst = NULL; |
596 | | /* providing nothing at all is a real use (mid-HRR) */ |
597 | 0 | if (buf != NULL && blen > 0) |
598 | 0 | BIO_write(s->s3.handshake_buffer, (void *)buf, (int)blen); |
599 | 0 | return 1; |
600 | 0 | } |
601 | | |
602 | | /* |
603 | | * To control the number of zeros added after an EncodedClientHello - we pad |
604 | | * to a target number of octets or, if there are naturally more, to a number |
605 | | * divisible by the defined increment (we also do the spec-recommended SNI |
606 | | * padding thing first) |
607 | | */ |
608 | 0 | #define OSSL_ECH_PADDING_TARGET 128 /* ECH cleartext padded to at least this */ |
609 | 0 | #define OSSL_ECH_PADDING_INCREMENT 32 /* ECH padded to a multiple of this */ |
610 | | |
611 | | /* |
612 | | * figure out how much padding for cleartext (on client) |
613 | | * ee is the chosen ECHConfig |
614 | | * return overall length to use including padding or zero on error |
615 | | * |
616 | | * "Recommended" inner SNI padding scheme as per spec (section 6.1.3) |
617 | | * Might remove the mnl stuff later - overall message padding seems |
618 | | * better really, BUT... we might want to keep this if others (e.g. |
619 | | * browsers) do it so as to not stand out compared to them. |
620 | | * |
621 | | * The "+ 9" constant below is from the specification and is the |
622 | | * expansion comparing a string length to an encoded SNI extension. |
623 | | * Same is true of the 31/32 formula below. |
624 | | * |
625 | | * Note that the AEAD tag will be added later, so if we e.g. have |
626 | | * a padded cleartext of 128 octets, the ciphertext will be 144 |
627 | | * octets. |
628 | | */ |
629 | | size_t ossl_ech_calc_padding(SSL_CONNECTION *s, OSSL_ECHSTORE_ENTRY *ee, |
630 | | size_t encoded_len) |
631 | 0 | { |
632 | 0 | size_t length_of_padding = 0, length_with_snipadding = 0; |
633 | 0 | size_t innersnipadding = 0, length_with_padding = 0; |
634 | 0 | size_t mnl = 0, isnilen = 0; |
635 | |
|
636 | 0 | if (s == NULL || ee == NULL) |
637 | 0 | return 0; |
638 | 0 | mnl = ee->max_name_length; |
639 | 0 | if (mnl != 0) { |
640 | | /* do weirder padding if SNI present in inner */ |
641 | 0 | if (s->ext.hostname != NULL) { |
642 | 0 | isnilen = strlen(s->ext.hostname) + 9; |
643 | 0 | innersnipadding = (mnl > isnilen) ? (int)(mnl - isnilen) : 0; |
644 | 0 | } else { |
645 | 0 | innersnipadding = (int)mnl + 9; |
646 | 0 | } |
647 | 0 | } |
648 | | /* padding is after the inner client hello has been encoded */ |
649 | 0 | length_with_snipadding = innersnipadding + (int)encoded_len; |
650 | 0 | length_of_padding = 31 - ((length_with_snipadding - 1) % 32); |
651 | 0 | length_with_padding = (int)encoded_len + length_of_padding |
652 | 0 | + innersnipadding; |
653 | | /* |
654 | | * Finally - make sure final result is longer than padding target |
655 | | * and a multiple of our padding increment. |
656 | | * This is a local addition - we might want to take it out if it makes |
657 | | * us stick out; or if we take out the above more (uselessly:-) |
658 | | * complicated scheme above, we may only need this in the end. |
659 | | */ |
660 | 0 | if ((length_with_padding % OSSL_ECH_PADDING_INCREMENT) != 0) |
661 | 0 | length_with_padding += OSSL_ECH_PADDING_INCREMENT |
662 | 0 | - (length_with_padding % OSSL_ECH_PADDING_INCREMENT); |
663 | 0 | while (length_with_padding < OSSL_ECH_PADDING_TARGET) |
664 | 0 | length_with_padding += OSSL_ECH_PADDING_INCREMENT; |
665 | 0 | OSSL_TRACE_BEGIN(TLS) |
666 | 0 | { |
667 | 0 | BIO_printf(trc_out, "EAAE: padding: mnl: %zu, lws: %zu " |
668 | 0 | "lop: %zu, clear_len (len with padding): %zu, orig: %zu\n", |
669 | 0 | mnl, length_with_snipadding, length_of_padding, |
670 | 0 | length_with_padding, encoded_len); |
671 | 0 | } |
672 | 0 | OSSL_TRACE_END(TLS); |
673 | 0 | return length_with_padding; |
674 | 0 | } |
675 | | |
676 | | /* |
677 | | * Calculate AAD and do ECH encryption |
678 | | * pkt is the packet to send |
679 | | * return 1 for success, other otherwise |
680 | | * |
681 | | * 1. Make up the AAD: the encoded outer, with ECH ciphertext octets zero'd |
682 | | * 2. Do the encryption |
683 | | * 3. Put the ECH back into the encoding |
684 | | * 4. Encode the outer (again!) |
685 | | */ |
686 | | int ossl_ech_aad_and_encrypt(SSL_CONNECTION *s, WPACKET *pkt) |
687 | 0 | { |
688 | 0 | int rv = 0; |
689 | 0 | size_t cipherlen = 0, aad_len = 0, mypub_len = 0, clear_len = 0; |
690 | 0 | size_t encoded_inner_len = 0; |
691 | 0 | unsigned char *clear = NULL, *aad = NULL, *mypub = NULL; |
692 | 0 | unsigned char *encoded_inner = NULL, *cipher_loc = NULL; |
693 | |
|
694 | 0 | if (s == NULL) |
695 | 0 | return 0; |
696 | 0 | if (s->ext.ech.es == NULL || s->ext.ech.es->entries == NULL |
697 | 0 | || pkt == NULL || s->ssl.ctx == NULL) { |
698 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
699 | 0 | goto err; |
700 | 0 | } |
701 | | /* values calculated in tls_construct_ctos_ech */ |
702 | 0 | encoded_inner = s->ext.ech.encoded_inner; |
703 | 0 | encoded_inner_len = s->ext.ech.encoded_inner_len; |
704 | 0 | clear_len = s->ext.ech.clearlen; |
705 | 0 | cipherlen = s->ext.ech.cipherlen; |
706 | 0 | if (!WPACKET_get_total_written(pkt, &aad_len) || aad_len < 4) { |
707 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
708 | 0 | goto err; |
709 | 0 | } |
710 | 0 | aad_len -= 4; /* ECH/HPKE aad starts after type + 3-octet len */ |
711 | 0 | aad = WPACKET_get_curr(pkt) - aad_len; |
712 | | /* where we'll replace zeros with ciphertext */ |
713 | 0 | cipher_loc = aad + s->ext.ech.cipher_offset; |
714 | | /* |
715 | | * close the extensions of the CH - we skipped doing this |
716 | | * earlier when encoding extensions, to allow for adding the |
717 | | * ECH here (when doing ECH) - see tls_construct_extensions() |
718 | | * towards the end |
719 | | */ |
720 | 0 | if (!WPACKET_close(pkt)) { |
721 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
722 | 0 | goto err; |
723 | 0 | } |
724 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
725 | 0 | ossl_ech_pbuf("EAAE: aad", aad, aad_len); |
726 | 0 | #endif |
727 | 0 | clear = OPENSSL_zalloc(clear_len); /* zeros incl. padding */ |
728 | 0 | if (clear == NULL) { |
729 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
730 | 0 | goto err; |
731 | 0 | } |
732 | 0 | memcpy(clear, encoded_inner, encoded_inner_len); |
733 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
734 | 0 | ossl_ech_pbuf("EAAE: padded clear", clear, clear_len); |
735 | 0 | #endif |
736 | | /* we're done with this now */ |
737 | 0 | OPENSSL_free(s->ext.ech.encoded_inner); |
738 | 0 | s->ext.ech.encoded_inner = NULL; |
739 | 0 | rv = OSSL_HPKE_seal(s->ext.ech.hpke_ctx, cipher_loc, |
740 | 0 | &cipherlen, aad, aad_len, clear, clear_len); |
741 | 0 | OPENSSL_free(clear); |
742 | 0 | if (rv != 1) { |
743 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
744 | 0 | goto err; |
745 | 0 | } |
746 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
747 | 0 | ossl_ech_pbuf("EAAE: cipher", cipher_loc, cipherlen); |
748 | 0 | ossl_ech_pbuf("EAAE: hpke mypub", mypub, mypub_len); |
749 | | /* re-use aad_len for tracing */ |
750 | 0 | WPACKET_get_total_written(pkt, &aad_len); |
751 | 0 | ossl_ech_pbuf("EAAE pkt aftr", WPACKET_get_curr(pkt) - aad_len, aad_len); |
752 | 0 | #endif |
753 | 0 | return 1; |
754 | 0 | err: |
755 | 0 | return 0; |
756 | 0 | } |
757 | | |
758 | | /* |
759 | | * print info about the ECH-status of an SSL connection |
760 | | * out is the BIO to use (e.g. stdout/whatever) |
761 | | * selector OSSL_ECH_SELECT_ALL or just one of the SSL_ECH values |
762 | | */ |
763 | | void ossl_ech_status_print(BIO *out, SSL_CONNECTION *s, int selector) |
764 | 0 | { |
765 | 0 | int num = 0, i, has_priv, for_retry; |
766 | 0 | size_t j; |
767 | 0 | time_t secs = 0; |
768 | 0 | char *pn = NULL, *ec = NULL; |
769 | 0 | OSSL_ECHSTORE *es = NULL; |
770 | |
|
771 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
772 | 0 | BIO_printf(out, "ech_status_print\n"); |
773 | 0 | BIO_printf(out, "s=%p\n", (void *)s); |
774 | 0 | #endif |
775 | 0 | BIO_printf(out, "ech_attempted=%d\n", s->ext.ech.attempted); |
776 | 0 | BIO_printf(out, "ech_attempted_type=0x%4x\n", |
777 | 0 | s->ext.ech.attempted_type); |
778 | 0 | if (s->ext.ech.attempted_cid == OSSL_ECH_config_id_unset) |
779 | 0 | BIO_printf(out, "ech_atttempted_cid is unset\n"); |
780 | 0 | else |
781 | 0 | BIO_printf(out, "ech_atttempted_cid=0x%02x\n", |
782 | 0 | s->ext.ech.attempted_cid); |
783 | 0 | BIO_printf(out, "ech_done=%d\n", s->ext.ech.done); |
784 | 0 | BIO_printf(out, "ech_grease=%d\n", s->ext.ech.grease); |
785 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
786 | 0 | BIO_printf(out, "HRR=%d\n", s->hello_retry_request); |
787 | 0 | #endif |
788 | 0 | BIO_printf(out, "ech_backend=%d\n", s->ext.ech.backend); |
789 | 0 | BIO_printf(out, "ech_success=%d\n", s->ext.ech.success); |
790 | 0 | es = s->ext.ech.es; |
791 | 0 | if (es == NULL || es->entries == NULL) { |
792 | 0 | BIO_printf(out, "ECH cfg=NONE\n"); |
793 | 0 | } else { |
794 | 0 | num = sk_OSSL_ECHSTORE_ENTRY_num(es->entries); |
795 | 0 | BIO_printf(out, "%d ECHConfig values loaded\n", num); |
796 | 0 | for (i = 0; i != num; i++) { |
797 | 0 | if (selector != OSSL_ECHSTORE_ALL && selector != i) |
798 | 0 | continue; |
799 | 0 | BIO_printf(out, "cfg(%d): ", i); |
800 | 0 | if (OSSL_ECHSTORE_get1_info(es, i, &secs, &pn, &ec, |
801 | 0 | &has_priv, &for_retry) |
802 | 0 | != 1) { |
803 | 0 | OPENSSL_free(pn); /* just in case */ |
804 | 0 | OPENSSL_free(ec); |
805 | 0 | continue; |
806 | 0 | } |
807 | 0 | BIO_printf(out, "ECH entry: %d public_name: %s age: %lld%s\n", |
808 | 0 | i, pn, (long long)secs, has_priv ? " (has private key)" : ""); |
809 | 0 | BIO_printf(out, "\t%s\n", ec); |
810 | 0 | OPENSSL_free(pn); |
811 | 0 | OPENSSL_free(ec); |
812 | 0 | } |
813 | 0 | } |
814 | 0 | if (s->ext.ech.returned) { |
815 | 0 | BIO_printf(out, "ret="); |
816 | 0 | for (j = 0; j != s->ext.ech.returned_len; j++) { |
817 | 0 | if (j != 0 && j % 16 == 0) |
818 | 0 | BIO_printf(out, "\n "); |
819 | 0 | BIO_printf(out, "%02x:", (unsigned)(s->ext.ech.returned[j])); |
820 | 0 | } |
821 | 0 | BIO_printf(out, "\n"); |
822 | 0 | } |
823 | 0 | return; |
824 | 0 | } |
825 | | |
826 | | /* |
827 | | * Swap the inner and outer after ECH success on the client |
828 | | * return 0 for error, 1 for success |
829 | | */ |
830 | | int ossl_ech_swaperoo(SSL_CONNECTION *s) |
831 | 0 | { |
832 | 0 | unsigned char *curr_buf = NULL; |
833 | 0 | size_t curr_buflen = 0; |
834 | |
|
835 | 0 | if (s == NULL) |
836 | 0 | return 0; |
837 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
838 | 0 | ossl_ech_ptranscript(s, "ech_swaperoo, b4"); |
839 | 0 | #endif |
840 | | /* un-stash inner key share(s) */ |
841 | 0 | if (ossl_ech_unstash_keyshares(s) != 1) { |
842 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
843 | 0 | return 0; |
844 | 0 | } |
845 | | /* |
846 | | * When not doing HRR... fix up the transcript to reflect the inner CH. |
847 | | * If there's a client hello at the start of the buffer, then that's |
848 | | * the outer CH and we want to replace that with the inner. We need to |
849 | | * be careful that there could be early data or a server hello following |
850 | | * and we can't lose that. |
851 | | * |
852 | | * For HRR... HRR processing code has already done the necessary. |
853 | | */ |
854 | 0 | if (s->hello_retry_request == SSL_HRR_NONE) { |
855 | 0 | BIO *handbuf = s->s3.handshake_buffer; |
856 | 0 | PACKET pkt, subpkt; |
857 | 0 | unsigned int mt; |
858 | |
|
859 | 0 | s->s3.handshake_buffer = NULL; |
860 | 0 | if (ssl3_init_finished_mac(s) == 0) { |
861 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
862 | 0 | BIO_free(handbuf); |
863 | 0 | return 0; |
864 | 0 | } |
865 | 0 | if (ssl3_finish_mac(s, s->ext.ech.innerch, s->ext.ech.innerch_len) == 0) { |
866 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
867 | 0 | BIO_free(handbuf); |
868 | 0 | return 0; |
869 | 0 | } |
870 | 0 | curr_buflen = BIO_get_mem_data(handbuf, &curr_buf); |
871 | 0 | if (PACKET_buf_init(&pkt, curr_buf, curr_buflen) |
872 | 0 | && PACKET_get_1(&pkt, &mt) |
873 | 0 | && mt == SSL3_MT_CLIENT_HELLO |
874 | 0 | && PACKET_remaining(&pkt) >= 3) { |
875 | 0 | if (!PACKET_get_length_prefixed_3(&pkt, &subpkt)) { |
876 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
877 | 0 | BIO_free(handbuf); |
878 | 0 | return 0; |
879 | 0 | } |
880 | 0 | if (PACKET_remaining(&pkt) > 0) { |
881 | 0 | if (ssl3_finish_mac(s, PACKET_data(&pkt), PACKET_remaining(&pkt)) == 0) { |
882 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
883 | 0 | BIO_free(handbuf); |
884 | 0 | return 0; |
885 | 0 | } |
886 | 0 | } |
887 | 0 | BIO_free(handbuf); |
888 | 0 | } |
889 | 0 | } |
890 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
891 | 0 | ossl_ech_ptranscript(s, "ech_swaperoo, after"); |
892 | 0 | #endif |
893 | | /* Declare victory! */ |
894 | 0 | s->ext.ech.attempted = 1; |
895 | 0 | s->ext.ech.success = 1; |
896 | 0 | s->ext.ech.done = 1; |
897 | 0 | s->ext.ech.grease = OSSL_ECH_NOT_GREASE; |
898 | | /* time to call an ECH callback, if there's one */ |
899 | 0 | if (s->ext.ech.es != NULL && s->ext.ech.done == 1 |
900 | 0 | && s->hello_retry_request != SSL_HRR_PENDING |
901 | 0 | && s->ext.ech.cb != NULL) { |
902 | 0 | char pstr[OSSL_ECH_PBUF_SIZE + 1] = { 0 }; |
903 | 0 | BIO *biom = BIO_new(BIO_s_mem()); |
904 | 0 | unsigned int cbrv = 0; |
905 | |
|
906 | 0 | if (biom == NULL) { |
907 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
908 | 0 | return 0; |
909 | 0 | } |
910 | 0 | ossl_ech_status_print(biom, s, OSSL_ECHSTORE_ALL); |
911 | 0 | BIO_read(biom, pstr, OSSL_ECH_PBUF_SIZE); |
912 | 0 | cbrv = s->ext.ech.cb(&s->ssl, pstr); |
913 | 0 | BIO_free(biom); |
914 | 0 | if (cbrv != 1) { |
915 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
916 | 0 | return 0; |
917 | 0 | } |
918 | 0 | } |
919 | 0 | return 1; |
920 | 0 | } |
921 | | |
922 | | /* |
923 | | * do the HKDF for ECH acceptance checking |
924 | | * md is the h/s hash |
925 | | * for_hrr is 1 if we're doing a HRR |
926 | | * hashval/hashlen is the transcript hash |
927 | | * hoval is the output, with the ECH acceptance signal |
928 | | * return 1 for good, 0 for error |
929 | | */ |
930 | | static int ech_hkdf_extract_wrap(SSL_CONNECTION *s, EVP_MD *md, int for_hrr, |
931 | | unsigned char *hashval, size_t hashlen, |
932 | | unsigned char hoval[OSSL_ECH_SIGNAL_LEN]) |
933 | 0 | { |
934 | 0 | int rv = 0; |
935 | 0 | unsigned char notsecret[EVP_MAX_MD_SIZE], zeros[EVP_MAX_MD_SIZE]; |
936 | 0 | size_t retlen = 0, labellen = 0; |
937 | 0 | EVP_PKEY_CTX *pctx = NULL; |
938 | 0 | const char *label = NULL; |
939 | 0 | unsigned char *p = NULL; |
940 | |
|
941 | 0 | if (for_hrr == 1) { |
942 | 0 | label = OSSL_ECH_HRR_CONFIRM_STRING; |
943 | 0 | labellen = sizeof(OSSL_ECH_HRR_CONFIRM_STRING) - 1; |
944 | 0 | } else { |
945 | 0 | label = OSSL_ECH_ACCEPT_CONFIRM_STRING; |
946 | 0 | labellen = sizeof(OSSL_ECH_ACCEPT_CONFIRM_STRING) - 1; |
947 | 0 | } |
948 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
949 | 0 | ossl_ech_pbuf("cc: label", (unsigned char *)label, labellen); |
950 | 0 | #endif |
951 | 0 | memset(zeros, 0, EVP_MAX_MD_SIZE); |
952 | | /* We don't seem to have an hkdf-extract that's exposed by libcrypto */ |
953 | 0 | pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); |
954 | 0 | if (pctx == NULL |
955 | 0 | || EVP_PKEY_derive_init(pctx) != 1 |
956 | 0 | || EVP_PKEY_CTX_hkdf_mode(pctx, |
957 | 0 | EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) |
958 | 0 | != 1 |
959 | 0 | || EVP_PKEY_CTX_set_hkdf_md(pctx, md) != 1) { |
960 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
961 | 0 | goto err; |
962 | 0 | } |
963 | | /* pick correct client_random */ |
964 | 0 | if (s->server) |
965 | 0 | p = s->s3.client_random; |
966 | 0 | else |
967 | 0 | p = s->ext.ech.client_random; |
968 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
969 | 0 | ossl_ech_pbuf("cc: client_random", p, SSL3_RANDOM_SIZE); |
970 | 0 | #endif |
971 | 0 | if (EVP_PKEY_CTX_set1_hkdf_key(pctx, p, SSL3_RANDOM_SIZE) != 1 |
972 | 0 | || EVP_PKEY_CTX_set1_hkdf_salt(pctx, zeros, (int)hashlen) != 1 |
973 | 0 | || EVP_PKEY_derive(pctx, NULL, &retlen) != 1 |
974 | 0 | || hashlen != retlen |
975 | 0 | || EVP_PKEY_derive(pctx, notsecret, &retlen) != 1) { |
976 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
977 | 0 | goto err; |
978 | 0 | } |
979 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
980 | 0 | ossl_ech_pbuf("cc: notsecret", notsecret, hashlen); |
981 | 0 | #endif |
982 | 0 | if (hashlen < OSSL_ECH_SIGNAL_LEN |
983 | 0 | || !tls13_hkdf_expand(s, md, notsecret, |
984 | 0 | (const unsigned char *)label, labellen, |
985 | 0 | hashval, hashlen, hoval, |
986 | 0 | OSSL_ECH_SIGNAL_LEN, 1)) { |
987 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
988 | 0 | goto err; |
989 | 0 | } |
990 | 0 | rv = 1; |
991 | 0 | err: |
992 | 0 | EVP_PKEY_CTX_free(pctx); |
993 | 0 | return rv; |
994 | 0 | } |
995 | | |
996 | | /* |
997 | | * ECH accept_confirmation calculation |
998 | | * for_hrr is 1 if this is for an HRR, otherwise for SH |
999 | | * acbuf is an 8 octet buffer for the confirmation value |
1000 | | * shlen is the server hello length |
1001 | | * return: 1 for success, 0 otherwise |
1002 | | * |
1003 | | * This is a magic value in the ServerHello.random lower 8 octets |
1004 | | * that is used to signal that the inner worked. |
1005 | | * |
1006 | | * As per spec: |
1007 | | * |
1008 | | * accept_confirmation = HKDF-Expand-Label( |
1009 | | * HKDF-Extract(0, ClientHelloInner.random), |
1010 | | * "ech accept confirmation", |
1011 | | * transcript_ech_conf, |
1012 | | * 8) |
1013 | | * |
1014 | | * transcript_ech_conf = ClientHelloInner..ServerHello |
1015 | | * with last 8 octets of ServerHello.random==0x00 |
1016 | | * |
1017 | | * and with differences due to HRR |
1018 | | */ |
1019 | | int ossl_ech_calc_confirm(SSL_CONNECTION *s, int for_hrr, |
1020 | | unsigned char acbuf[OSSL_ECH_SIGNAL_LEN], |
1021 | | const size_t shlen) |
1022 | 0 | { |
1023 | 0 | int rv = 0; |
1024 | 0 | EVP_MD_CTX *ctx = NULL; |
1025 | 0 | EVP_MD *md = NULL; |
1026 | 0 | unsigned char *tbuf = NULL, *conf_loc = NULL; |
1027 | 0 | unsigned char *fixedshbuf = NULL; |
1028 | 0 | size_t fixedshbuf_len = 0, tlen = 0, chend = 0; |
1029 | | /* shoffset is: 4 + 2 + 32 - 8 */ |
1030 | 0 | size_t shoffset = SSL3_HM_HEADER_LENGTH + sizeof(uint16_t) |
1031 | 0 | + SSL3_RANDOM_SIZE - OSSL_ECH_SIGNAL_LEN; |
1032 | 0 | unsigned int hashlen = 0; |
1033 | 0 | unsigned char hashval[EVP_MAX_MD_SIZE]; |
1034 | 0 | SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); |
1035 | |
|
1036 | 0 | if ((md = (EVP_MD *)ssl_handshake_md(s)) == NULL) { |
1037 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_ECH_REQUIRED); |
1038 | 0 | goto end; |
1039 | 0 | } |
1040 | 0 | if (ossl_ech_intbuf_fetch(s, &tbuf, &tlen) != 1) { |
1041 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_ECH_REQUIRED); |
1042 | 0 | goto end; |
1043 | 0 | } |
1044 | 0 | chend = tlen - shlen - 4; |
1045 | 0 | fixedshbuf_len = shlen + 4; |
1046 | 0 | if (s->server) { |
1047 | 0 | chend = tlen - shlen; |
1048 | 0 | fixedshbuf_len = shlen; |
1049 | 0 | } |
1050 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1051 | 0 | ossl_ech_pbuf("cx: tbuf b4-b4", tbuf, tlen); |
1052 | 0 | #endif |
1053 | | /* put zeros in correct place */ |
1054 | 0 | if (for_hrr == 0) { /* zap magic octets at fixed place for SH */ |
1055 | 0 | conf_loc = tbuf + chend + shoffset; |
1056 | 0 | } else { |
1057 | 0 | if (s->server == 1) { /* we get to say where we put ECH:-) */ |
1058 | 0 | conf_loc = tbuf + tlen - OSSL_ECH_SIGNAL_LEN; |
1059 | 0 | } else { |
1060 | 0 | if (s->ext.ech.hrrsignal_p == NULL) { |
1061 | | /* No ECH found so we'll exit, but set random output */ |
1062 | 0 | if (RAND_bytes_ex(sctx->libctx, acbuf, |
1063 | 0 | OSSL_ECH_SIGNAL_LEN, 0) |
1064 | 0 | <= 0) { |
1065 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_ECH_REQUIRED); |
1066 | 0 | goto end; |
1067 | 0 | } |
1068 | 0 | rv = 1; |
1069 | 0 | goto end; |
1070 | 0 | } |
1071 | 0 | conf_loc = s->ext.ech.hrrsignal_p; |
1072 | 0 | } |
1073 | 0 | } |
1074 | 0 | memset(conf_loc, 0, OSSL_ECH_SIGNAL_LEN); |
1075 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1076 | 0 | ossl_ech_pbuf("cx: tbuf after", tbuf, tlen); |
1077 | 0 | #endif |
1078 | 0 | if ((ctx = EVP_MD_CTX_new()) == NULL |
1079 | 0 | || EVP_DigestInit_ex(ctx, md, NULL) <= 0 |
1080 | 0 | || EVP_DigestUpdate(ctx, tbuf, tlen) <= 0 |
1081 | 0 | || EVP_DigestFinal_ex(ctx, hashval, &hashlen) <= 0) { |
1082 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1083 | 0 | goto end; |
1084 | 0 | } |
1085 | 0 | EVP_MD_CTX_free(ctx); |
1086 | 0 | ctx = NULL; |
1087 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1088 | 0 | ossl_ech_pbuf("cx: hashval", hashval, hashlen); |
1089 | 0 | #endif |
1090 | | /* calculate and set the final output */ |
1091 | 0 | if (ech_hkdf_extract_wrap(s, md, for_hrr, hashval, hashlen, acbuf) != 1) { |
1092 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1093 | 0 | goto end; |
1094 | 0 | } |
1095 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1096 | 0 | ossl_ech_pbuf("cx: result", acbuf, OSSL_ECH_SIGNAL_LEN); |
1097 | 0 | #endif |
1098 | | /* put confirm value back into transcript */ |
1099 | 0 | memcpy(conf_loc, acbuf, OSSL_ECH_SIGNAL_LEN); |
1100 | | /* on a server, we need to reset the hs buffer now */ |
1101 | 0 | if (s->server && s->hello_retry_request == SSL_HRR_NONE) |
1102 | 0 | ossl_ech_reset_hs_buffer(s, s->ext.ech.innerch, s->ext.ech.innerch_len); |
1103 | 0 | if (s->server && s->hello_retry_request == SSL_HRR_COMPLETE) |
1104 | 0 | ossl_ech_reset_hs_buffer(s, tbuf, tlen - fixedshbuf_len); |
1105 | 0 | rv = 1; |
1106 | 0 | end: |
1107 | 0 | OPENSSL_free(fixedshbuf); |
1108 | 0 | EVP_MD_CTX_free(ctx); |
1109 | 0 | return rv; |
1110 | 0 | } |
1111 | | |
1112 | | /*! |
1113 | | * Given a CH find the offsets of the session id, extensions and ECH |
1114 | | * pkt is the CH |
1115 | | * sessid_off points to offset of session_id length |
1116 | | * exts_off points to offset of extensions |
1117 | | * ech_off points to offset of ECH |
1118 | | * echtype points to the ext type of the ECH |
1119 | | * inner 1 if the ECH is marked as an inner, 0 for outer |
1120 | | * sni_off points to offset of (outer) SNI |
1121 | | * return 1 for success, other otherwise |
1122 | | * |
1123 | | * Offsets are set to zero if relevant thing not found. |
1124 | | * Offsets are returned to the type or length field in question. |
1125 | | * |
1126 | | * Note: input here is untrusted! |
1127 | | */ |
1128 | | int ossl_ech_get_ch_offsets(SSL_CONNECTION *s, PACKET *pkt, size_t *sessid_off, |
1129 | | size_t *exts_off, size_t *ech_off, uint16_t *echtype, |
1130 | | int *inner, size_t *sni_off) |
1131 | 0 | { |
1132 | 0 | const unsigned char *ch = NULL; |
1133 | 0 | size_t ch_len = 0, exts_len = 0, sni_len = 0, ech_len = 0; |
1134 | |
|
1135 | 0 | if (s == NULL) |
1136 | 0 | return 0; |
1137 | 0 | if (pkt == NULL || sessid_off == NULL || exts_off == NULL |
1138 | 0 | || ech_off == NULL || echtype == NULL || inner == NULL |
1139 | 0 | || sni_off == NULL) { |
1140 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1141 | 0 | return 0; |
1142 | 0 | } |
1143 | | /* check if we've already done the work */ |
1144 | 0 | if (s->ext.ech.ch_offsets_done == 1) { |
1145 | 0 | *sessid_off = s->ext.ech.sessid_off; |
1146 | 0 | *exts_off = s->ext.ech.exts_off; |
1147 | 0 | *ech_off = s->ext.ech.ech_off; |
1148 | 0 | *echtype = s->ext.ech.echtype; |
1149 | 0 | *inner = s->ext.ech.inner; |
1150 | 0 | *sni_off = s->ext.ech.sni_off; |
1151 | 0 | return 1; |
1152 | 0 | } |
1153 | 0 | *sessid_off = 0; |
1154 | 0 | *exts_off = 0; |
1155 | 0 | *ech_off = 0; |
1156 | 0 | *echtype = OSSL_ECH_type_unknown; |
1157 | 0 | *sni_off = 0; |
1158 | | /* do the work */ |
1159 | 0 | ch_len = PACKET_remaining(pkt); |
1160 | 0 | if (PACKET_peek_bytes(pkt, &ch, ch_len) != 1) { |
1161 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1162 | 0 | return 0; |
1163 | 0 | } |
1164 | 0 | if (ossl_ech_helper_get_ch_offsets(ch, ch_len, sessid_off, exts_off, |
1165 | 0 | &exts_len, ech_off, echtype, &ech_len, |
1166 | 0 | sni_off, &sni_len, inner) |
1167 | 0 | != 1) { |
1168 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1169 | 0 | return 0; |
1170 | 0 | } |
1171 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1172 | 0 | OSSL_TRACE_BEGIN(TLS) |
1173 | 0 | { |
1174 | 0 | BIO_printf(trc_out, "orig CH/ECH type: %4x\n", *echtype); |
1175 | 0 | } |
1176 | 0 | OSSL_TRACE_END(TLS); |
1177 | 0 | ossl_ech_pbuf("orig CH", (unsigned char *)ch, ch_len); |
1178 | 0 | ossl_ech_pbuf("orig CH exts", (unsigned char *)ch + *exts_off, exts_len); |
1179 | 0 | ossl_ech_pbuf("orig CH/ECH", (unsigned char *)ch + *ech_off, ech_len); |
1180 | 0 | ossl_ech_pbuf("orig CH SNI", (unsigned char *)ch + *sni_off, sni_len); |
1181 | 0 | #endif |
1182 | 0 | s->ext.ech.sessid_off = *sessid_off; |
1183 | 0 | s->ext.ech.exts_off = *exts_off; |
1184 | 0 | s->ext.ech.ech_off = *ech_off; |
1185 | 0 | s->ext.ech.echtype = *echtype; |
1186 | 0 | s->ext.ech.inner = *inner; |
1187 | 0 | s->ext.ech.sni_off = *sni_off; |
1188 | 0 | s->ext.ech.ch_offsets_done = 1; |
1189 | 0 | return 1; |
1190 | 0 | } |
1191 | | |
1192 | | static void ossl_ech_encch_free(OSSL_ECH_ENCCH *tbf) |
1193 | 0 | { |
1194 | 0 | if (tbf == NULL) |
1195 | 0 | return; |
1196 | 0 | OPENSSL_free(tbf->enc); |
1197 | 0 | OPENSSL_free(tbf->payload); |
1198 | 0 | return; |
1199 | 0 | } |
1200 | | |
1201 | | /* |
1202 | | * decode outer sni value so we can trace it |
1203 | | * osni_str is the string-form of the SNI |
1204 | | * opd is the outer CH buffer |
1205 | | * opl is the length of the above |
1206 | | * snioffset is where we find the outer SNI |
1207 | | * |
1208 | | * The caller doesn't have to free the osni_str. |
1209 | | */ |
1210 | | static int ech_get_outer_sni(SSL_CONNECTION *s, char **osni_str, |
1211 | | const unsigned char *opd, size_t opl, |
1212 | | size_t snioffset) |
1213 | 0 | { |
1214 | 0 | PACKET wrap, osni; |
1215 | 0 | unsigned int type, osnilen; |
1216 | |
|
1217 | 0 | if (snioffset >= opl |
1218 | 0 | || !PACKET_buf_init(&wrap, opd + snioffset, opl - snioffset) |
1219 | 0 | || !PACKET_get_net_2(&wrap, &type) |
1220 | 0 | || type != 0 |
1221 | 0 | || !PACKET_get_net_2(&wrap, &osnilen) |
1222 | 0 | || !PACKET_get_sub_packet(&wrap, &osni, osnilen) |
1223 | 0 | || tls_parse_ctos_server_name(s, &osni, 0, NULL, 0) != 1) |
1224 | 0 | return 0; |
1225 | 0 | OPENSSL_free(s->ext.ech.outer_hostname); |
1226 | 0 | *osni_str = s->ext.ech.outer_hostname = s->ext.hostname; |
1227 | | /* clean up what the ECH-unaware parse func above left behind */ |
1228 | 0 | s->ext.hostname = NULL; |
1229 | 0 | s->servername_done = 0; |
1230 | 0 | return 1; |
1231 | 0 | } |
1232 | | |
1233 | | /* |
1234 | | * decode EncryptedClientHello extension value |
1235 | | * pkt contains the ECH value as a PACKET |
1236 | | * retext is the returned decoded structure |
1237 | | * payload_offset is the offset to the ciphertext |
1238 | | * return 1 for good, 0 for bad |
1239 | | * |
1240 | | * SSLfatal called from inside, as needed |
1241 | | */ |
1242 | | static int ech_decode_inbound_ech(SSL_CONNECTION *s, PACKET *pkt, |
1243 | | OSSL_ECH_ENCCH **retext, |
1244 | | size_t *payload_offset) |
1245 | 0 | { |
1246 | 0 | unsigned int innerorouter = 0xff; |
1247 | 0 | unsigned int pval_tmp; /* tmp placeholder of value from packet */ |
1248 | 0 | OSSL_ECH_ENCCH *extval = NULL; |
1249 | 0 | const unsigned char *startofech = NULL; |
1250 | | |
1251 | | /* |
1252 | | * Decode the inbound ECH value. |
1253 | | * enum { outer(0), inner(1) } ECHClientHelloType; |
1254 | | * struct { |
1255 | | * ECHClientHelloType type; |
1256 | | * select (ECHClientHello.type) { |
1257 | | * case outer: |
1258 | | * HpkeSymmetricCipherSuite cipher_suite; |
1259 | | * uint8 config_id; |
1260 | | * opaque enc<0..2^16-1>; |
1261 | | * opaque payload<1..2^16-1>; |
1262 | | * case inner: |
1263 | | * Empty; |
1264 | | * }; |
1265 | | * } ECHClientHello; |
1266 | | */ |
1267 | 0 | startofech = PACKET_data(pkt); |
1268 | 0 | extval = OPENSSL_zalloc(sizeof(OSSL_ECH_ENCCH)); |
1269 | 0 | if (extval == NULL) |
1270 | 0 | goto err; |
1271 | 0 | if (!PACKET_get_1(pkt, &innerorouter)) { |
1272 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1273 | 0 | goto err; |
1274 | 0 | } |
1275 | 0 | if (innerorouter != OSSL_ECH_OUTER_CH_TYPE) { |
1276 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1277 | 0 | goto err; |
1278 | 0 | } |
1279 | 0 | if (!PACKET_get_net_2(pkt, &pval_tmp)) { |
1280 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1281 | 0 | goto err; |
1282 | 0 | } |
1283 | 0 | extval->kdf_id = pval_tmp & 0xffff; |
1284 | 0 | if (!PACKET_get_net_2(pkt, &pval_tmp)) { |
1285 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1286 | 0 | goto err; |
1287 | 0 | } |
1288 | 0 | extval->aead_id = pval_tmp & 0xffff; |
1289 | | /* config id */ |
1290 | 0 | if (!PACKET_copy_bytes(pkt, &extval->config_id, 1)) { |
1291 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1292 | 0 | goto err; |
1293 | 0 | } |
1294 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1295 | 0 | ossl_ech_pbuf("EARLY config id", &extval->config_id, 1); |
1296 | 0 | #endif |
1297 | 0 | s->ext.ech.attempted_cid = extval->config_id; |
1298 | | /* enc - the client's public share */ |
1299 | 0 | if (!PACKET_get_net_2(pkt, &pval_tmp)) { |
1300 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1301 | 0 | goto err; |
1302 | 0 | } |
1303 | 0 | if (pval_tmp > OSSL_ECH_MAX_GREASE_PUB) { |
1304 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1305 | 0 | goto err; |
1306 | 0 | } |
1307 | 0 | if (pval_tmp > PACKET_remaining(pkt)) { |
1308 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1309 | 0 | goto err; |
1310 | 0 | } |
1311 | 0 | if (pval_tmp == 0 && s->hello_retry_request != SSL_HRR_PENDING) { |
1312 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1313 | 0 | goto err; |
1314 | 0 | } else if (pval_tmp > 0 && s->hello_retry_request == SSL_HRR_PENDING) { |
1315 | 0 | unsigned char *tmpenc = NULL; |
1316 | | |
1317 | | /* |
1318 | | * if doing HRR, client should only send this when GREASEing |
1319 | | * and it should be the same value as 1st time, so we'll check |
1320 | | * that |
1321 | | */ |
1322 | 0 | if (s->ext.ech.pub == NULL || s->ext.ech.pub_len == 0) { |
1323 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1324 | 0 | goto err; |
1325 | 0 | } |
1326 | 0 | if (pval_tmp != s->ext.ech.pub_len) { |
1327 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1328 | 0 | goto err; |
1329 | 0 | } |
1330 | 0 | tmpenc = OPENSSL_malloc(pval_tmp); |
1331 | 0 | if (tmpenc == NULL) |
1332 | 0 | goto err; |
1333 | 0 | if (!PACKET_copy_bytes(pkt, tmpenc, pval_tmp)) { |
1334 | 0 | OPENSSL_free(tmpenc); |
1335 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1336 | 0 | goto err; |
1337 | 0 | } |
1338 | 0 | if (memcmp(tmpenc, s->ext.ech.pub, pval_tmp) != 0) { |
1339 | 0 | OPENSSL_free(tmpenc); |
1340 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1341 | 0 | goto err; |
1342 | 0 | } |
1343 | 0 | OPENSSL_free(tmpenc); |
1344 | 0 | } else if (pval_tmp == 0 && s->hello_retry_request == SSL_HRR_PENDING) { |
1345 | 0 | if (s->ext.ech.pub == NULL || s->ext.ech.pub_len == 0) { |
1346 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1347 | 0 | goto err; |
1348 | 0 | } |
1349 | 0 | extval->enc_len = s->ext.ech.pub_len; |
1350 | 0 | extval->enc = OPENSSL_malloc(extval->enc_len); |
1351 | 0 | if (extval->enc == NULL) |
1352 | 0 | goto err; |
1353 | 0 | memcpy(extval->enc, s->ext.ech.pub, extval->enc_len); |
1354 | 0 | } else { |
1355 | 0 | extval->enc_len = pval_tmp; |
1356 | 0 | extval->enc = OPENSSL_malloc(pval_tmp); |
1357 | 0 | if (extval->enc == NULL) |
1358 | 0 | goto err; |
1359 | 0 | if (!PACKET_copy_bytes(pkt, extval->enc, pval_tmp)) { |
1360 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1361 | 0 | goto err; |
1362 | 0 | } |
1363 | | /* squirrel away that value in case of future HRR */ |
1364 | 0 | OPENSSL_free(s->ext.ech.pub); |
1365 | 0 | s->ext.ech.pub_len = extval->enc_len; |
1366 | 0 | s->ext.ech.pub = OPENSSL_malloc(extval->enc_len); |
1367 | 0 | if (s->ext.ech.pub == NULL) |
1368 | 0 | goto err; |
1369 | 0 | memcpy(s->ext.ech.pub, extval->enc, extval->enc_len); |
1370 | 0 | } |
1371 | | /* payload - the encrypted CH */ |
1372 | 0 | *payload_offset = PACKET_data(pkt) - startofech; |
1373 | 0 | if (!PACKET_get_net_2(pkt, &pval_tmp)) { |
1374 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1375 | 0 | goto err; |
1376 | 0 | } |
1377 | 0 | if (pval_tmp > OSSL_ECH_MAX_PAYLOAD_LEN) { |
1378 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1379 | 0 | goto err; |
1380 | 0 | } |
1381 | 0 | if (pval_tmp == 0 || pval_tmp > PACKET_remaining(pkt)) { |
1382 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1383 | 0 | goto err; |
1384 | 0 | } |
1385 | 0 | extval->payload_len = pval_tmp; |
1386 | 0 | extval->payload = OPENSSL_malloc(pval_tmp); |
1387 | 0 | if (extval->payload == NULL) |
1388 | 0 | goto err; |
1389 | 0 | if (!PACKET_copy_bytes(pkt, extval->payload, pval_tmp)) { |
1390 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1391 | 0 | goto err; |
1392 | 0 | } |
1393 | 0 | *retext = extval; |
1394 | 0 | return 1; |
1395 | 0 | err: |
1396 | 0 | if (extval != NULL) { |
1397 | 0 | ossl_ech_encch_free(extval); |
1398 | 0 | OPENSSL_free(extval); |
1399 | 0 | extval = NULL; |
1400 | 0 | } |
1401 | 0 | return 0; |
1402 | 0 | } |
1403 | | |
1404 | | /* |
1405 | | * find outers if any, and do initial checks |
1406 | | * pkt is the encoded inner |
1407 | | * outers is the array of outer ext types |
1408 | | * n_outers is the number of outers found |
1409 | | * return 1 for good, 0 for error |
1410 | | * |
1411 | | * recall we're dealing with recovered ECH plaintext here so |
1412 | | * the content must be a TLSv1.3 ECH encoded inner |
1413 | | */ |
1414 | | static int ech_find_outers(SSL_CONNECTION *s, PACKET *pkt, |
1415 | | uint16_t *outers, size_t *n_outers) |
1416 | 0 | { |
1417 | 0 | const unsigned char *pp_tmp; |
1418 | 0 | unsigned int pi_tmp, extlens, etype, elen, olen; |
1419 | 0 | int outers_found = 0; |
1420 | 0 | size_t i; |
1421 | 0 | PACKET op; |
1422 | |
|
1423 | 0 | PACKET_null_init(&op); |
1424 | | /* chew up the packet to extensions */ |
1425 | 0 | if (!PACKET_get_net_2(pkt, &pi_tmp) |
1426 | 0 | || pi_tmp != TLS1_2_VERSION |
1427 | 0 | || !PACKET_get_bytes(pkt, &pp_tmp, SSL3_RANDOM_SIZE) |
1428 | 0 | || !PACKET_get_1(pkt, &pi_tmp) |
1429 | 0 | || pi_tmp != 0x00 /* zero'd session id */ |
1430 | 0 | || !PACKET_get_net_2(pkt, &pi_tmp) /* ciphersuite len */ |
1431 | 0 | || !PACKET_get_bytes(pkt, &pp_tmp, pi_tmp) /* suites */ |
1432 | 0 | || !PACKET_get_1(pkt, &pi_tmp) /* compression meths */ |
1433 | 0 | || pi_tmp != 0x01 /* 1 octet of comressions */ |
1434 | 0 | || !PACKET_get_1(pkt, &pi_tmp) /* compression meths */ |
1435 | 0 | || pi_tmp != 0x00 /* 1 octet of no comressions */ |
1436 | 0 | || !PACKET_get_net_2(pkt, &extlens) /* len(extensions) */ |
1437 | 0 | || extlens == 0) { /* no extensions! */ |
1438 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1439 | 0 | goto err; |
1440 | 0 | } |
1441 | 0 | while (PACKET_remaining(pkt) > 0 && outers_found == 0) { |
1442 | 0 | if (!PACKET_get_net_2(pkt, &etype)) { |
1443 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1444 | 0 | goto err; |
1445 | 0 | } |
1446 | 0 | if (etype == TLSEXT_TYPE_outer_extensions) { |
1447 | 0 | outers_found = 1; |
1448 | 0 | if (!PACKET_get_length_prefixed_2(pkt, &op)) { |
1449 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1450 | 0 | goto err; |
1451 | 0 | } |
1452 | 0 | } else { /* skip over */ |
1453 | 0 | if (!PACKET_get_net_2(pkt, &elen) |
1454 | 0 | || !PACKET_get_bytes(pkt, &pp_tmp, elen)) { |
1455 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1456 | 0 | goto err; |
1457 | 0 | } |
1458 | 0 | } |
1459 | 0 | } |
1460 | | |
1461 | 0 | if (outers_found == 0) { /* which is fine! */ |
1462 | 0 | *n_outers = 0; |
1463 | 0 | return 1; |
1464 | 0 | } |
1465 | | /* |
1466 | | * outers has a silly internal length as well and that better |
1467 | | * be one less than the extension length and an even number |
1468 | | * and we only support a certain max of outers |
1469 | | */ |
1470 | 0 | if (!PACKET_get_1(&op, &olen) |
1471 | 0 | || olen % 2 == 1 |
1472 | 0 | || olen / 2 > OSSL_ECH_OUTERS_MAX) { |
1473 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1474 | 0 | goto err; |
1475 | 0 | } |
1476 | 0 | *n_outers = olen / 2; |
1477 | 0 | for (i = 0; i != *n_outers; i++) { |
1478 | 0 | if (!PACKET_get_net_2(&op, &pi_tmp) |
1479 | 0 | || pi_tmp == TLSEXT_TYPE_outer_extensions) { |
1480 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1481 | 0 | goto err; |
1482 | 0 | } |
1483 | 0 | outers[i] = (uint16_t)pi_tmp; |
1484 | 0 | } |
1485 | 0 | return 1; |
1486 | 0 | err: |
1487 | 0 | return 0; |
1488 | 0 | } |
1489 | | |
1490 | | /* |
1491 | | * copy one extension from outer to inner |
1492 | | * di is the reconstituted inner CH |
1493 | | * type2copy is the outer type to copy |
1494 | | * extsbuf is the outer extensions buffer |
1495 | | * extslen is the outer extensions buffer length |
1496 | | * return 1 for good 0 for error |
1497 | | */ |
1498 | | static int ech_copy_ext(SSL_CONNECTION *s, WPACKET *di, uint16_t type2copy, |
1499 | | const unsigned char *extsbuf, size_t extslen) |
1500 | 0 | { |
1501 | 0 | PACKET exts; |
1502 | 0 | unsigned int etype, elen; |
1503 | 0 | const unsigned char *eval; |
1504 | |
|
1505 | 0 | if (PACKET_buf_init(&exts, extsbuf, extslen) != 1) { |
1506 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1507 | 0 | goto err; |
1508 | 0 | } |
1509 | 0 | while (PACKET_remaining(&exts) > 0) { |
1510 | 0 | if (!PACKET_get_net_2(&exts, &etype) |
1511 | 0 | || !PACKET_get_net_2(&exts, &elen) |
1512 | 0 | || !PACKET_get_bytes(&exts, &eval, elen)) { |
1513 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1514 | 0 | goto err; |
1515 | 0 | } |
1516 | 0 | if (etype == type2copy) { |
1517 | 0 | if (!WPACKET_put_bytes_u16(di, etype) |
1518 | 0 | || !WPACKET_put_bytes_u16(di, elen) |
1519 | 0 | || !WPACKET_memcpy(di, eval, elen)) { |
1520 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1521 | 0 | goto err; |
1522 | 0 | } |
1523 | 0 | return 1; |
1524 | 0 | } |
1525 | 0 | } |
1526 | | /* we didn't find such an extension - that's an error */ |
1527 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1528 | 0 | err: |
1529 | 0 | return 0; |
1530 | 0 | } |
1531 | | |
1532 | | /* |
1533 | | * reconstitute the inner CH from encoded inner and outers |
1534 | | * di is the reconstituted inner CH |
1535 | | * ei is the encoded inner |
1536 | | * ob is the outer CH as a buffer |
1537 | | * ob_len is the size of the above |
1538 | | * outers is the array of outer ext types |
1539 | | * n_outers is the number of outers found |
1540 | | * return 1 for good, 0 for error |
1541 | | */ |
1542 | | static int ech_reconstitute_inner(SSL_CONNECTION *s, WPACKET *di, PACKET *ei, |
1543 | | const unsigned char *ob, size_t ob_len, |
1544 | | uint16_t *outers, size_t n_outers) |
1545 | 0 | { |
1546 | 0 | const unsigned char *pp_tmp, *eval, *outer_exts; |
1547 | 0 | unsigned int pi_tmp, etype, elen, outer_extslen; |
1548 | 0 | PACKET outer, session_id; |
1549 | 0 | size_t i; |
1550 | |
|
1551 | 0 | if (PACKET_buf_init(&outer, ob, ob_len) != 1) { |
1552 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1553 | 0 | goto err; |
1554 | 0 | } |
1555 | | /* read/write from encoded inner to decoded inner with help from outer */ |
1556 | 0 | if (/* version */ |
1557 | 0 | !PACKET_get_net_2(&outer, &pi_tmp) |
1558 | 0 | || !PACKET_get_net_2(ei, &pi_tmp) |
1559 | 0 | || !WPACKET_put_bytes_u16(di, pi_tmp) |
1560 | | |
1561 | | /* client random */ |
1562 | 0 | || !PACKET_get_bytes(&outer, &pp_tmp, SSL3_RANDOM_SIZE) |
1563 | 0 | || !PACKET_get_bytes(ei, &pp_tmp, SSL3_RANDOM_SIZE) |
1564 | 0 | || !WPACKET_memcpy(di, pp_tmp, SSL3_RANDOM_SIZE) |
1565 | | |
1566 | | /* session ID */ |
1567 | 0 | || !PACKET_get_1(ei, &pi_tmp) |
1568 | 0 | || !PACKET_get_length_prefixed_1(&outer, &session_id) |
1569 | 0 | || !WPACKET_start_sub_packet_u8(di) |
1570 | 0 | || (PACKET_remaining(&session_id) != 0 |
1571 | 0 | && !WPACKET_memcpy(di, PACKET_data(&session_id), |
1572 | 0 | PACKET_remaining(&session_id))) |
1573 | 0 | || !WPACKET_close(di) |
1574 | | |
1575 | | /* ciphersuites */ |
1576 | 0 | || !PACKET_get_net_2(&outer, &pi_tmp) /* ciphersuite len */ |
1577 | 0 | || !PACKET_get_bytes(&outer, &pp_tmp, pi_tmp) /* suites */ |
1578 | 0 | || !PACKET_get_net_2(ei, &pi_tmp) /* ciphersuite len */ |
1579 | 0 | || !PACKET_get_bytes(ei, &pp_tmp, pi_tmp) /* suites */ |
1580 | 0 | || !WPACKET_put_bytes_u16(di, pi_tmp) |
1581 | 0 | || !WPACKET_memcpy(di, pp_tmp, pi_tmp) |
1582 | | |
1583 | | /* compression len & meth */ |
1584 | 0 | || !PACKET_get_net_2(ei, &pi_tmp) |
1585 | 0 | || !PACKET_get_net_2(&outer, &pi_tmp) |
1586 | 0 | || !WPACKET_put_bytes_u16(di, pi_tmp)) { |
1587 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1588 | 0 | goto err; |
1589 | 0 | } |
1590 | | /* handle simple, but unlikely, case first */ |
1591 | 0 | if (n_outers == 0) { |
1592 | 0 | if (PACKET_remaining(ei) == 0) |
1593 | 0 | return 1; /* no exts is theoretically possible */ |
1594 | 0 | if (!PACKET_get_net_2(ei, &pi_tmp) /* len(extensions) */ |
1595 | 0 | || !PACKET_get_bytes(ei, &pp_tmp, pi_tmp) |
1596 | 0 | || !WPACKET_put_bytes_u16(di, pi_tmp) |
1597 | 0 | || !WPACKET_memcpy(di, pp_tmp, pi_tmp)) { |
1598 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1599 | 0 | goto err; |
1600 | 0 | } |
1601 | 0 | WPACKET_close(di); |
1602 | 0 | return 1; |
1603 | 0 | } |
1604 | | /* |
1605 | | * general case, copy one by one from inner, 'till we hit |
1606 | | * the outers extension, then copy one by one from outer |
1607 | | */ |
1608 | 0 | if (!PACKET_get_net_2(ei, &pi_tmp) /* len(extensions) */ |
1609 | 0 | || !PACKET_get_net_2(&outer, &outer_extslen) |
1610 | 0 | || !PACKET_get_bytes(&outer, &outer_exts, outer_extslen) |
1611 | 0 | || !WPACKET_start_sub_packet_u16(di)) { |
1612 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1613 | 0 | goto err; |
1614 | 0 | } |
1615 | 0 | while (PACKET_remaining(ei) > 0) { |
1616 | 0 | if (!PACKET_get_net_2(ei, &etype) |
1617 | 0 | || !PACKET_get_net_2(ei, &elen) |
1618 | 0 | || !PACKET_get_bytes(ei, &eval, elen)) { |
1619 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1620 | 0 | goto err; |
1621 | 0 | } |
1622 | 0 | if (etype == TLSEXT_TYPE_outer_extensions) { |
1623 | 0 | for (i = 0; i != n_outers; i++) { |
1624 | 0 | if (ech_copy_ext(s, di, outers[i], |
1625 | 0 | outer_exts, outer_extslen) |
1626 | 0 | != 1) |
1627 | | /* SSLfatal called already */ |
1628 | 0 | goto err; |
1629 | 0 | } |
1630 | 0 | } else { |
1631 | 0 | if (!WPACKET_put_bytes_u16(di, etype) |
1632 | 0 | || !WPACKET_put_bytes_u16(di, elen) |
1633 | 0 | || !WPACKET_memcpy(di, eval, elen)) { |
1634 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1635 | 0 | goto err; |
1636 | 0 | } |
1637 | 0 | } |
1638 | 0 | } |
1639 | 0 | WPACKET_close(di); |
1640 | 0 | return 1; |
1641 | 0 | err: |
1642 | 0 | WPACKET_cleanup(di); |
1643 | 0 | return 0; |
1644 | 0 | } |
1645 | | |
1646 | | /* |
1647 | | * After successful ECH decrypt, we decode, decompress etc. |
1648 | | * ob is the outer CH as a buffer |
1649 | | * ob_len is the size of the above |
1650 | | * return 1 for success, error otherwise |
1651 | | * |
1652 | | * We need the outer CH as a buffer (ob, below) so we can |
1653 | | * ECH-decompress. |
1654 | | * The plaintext we start from is in encoded_innerch |
1655 | | * and our final decoded, decompressed buffer will end up |
1656 | | * in innerch (which'll then be further processed). |
1657 | | * That further processing includes all existing decoding |
1658 | | * checks so we should be fine wrt fuzzing without having |
1659 | | * to make all checks here (e.g. we can assume that the |
1660 | | * protocol version, NULL compression etc are correct here - |
1661 | | * if not, those'll be caught later). |
1662 | | * Note: there are a lot of literal values here, but it's |
1663 | | * not clear that changing those to #define'd symbols will |
1664 | | * help much - a change to the length of a type or from a |
1665 | | * 2 octet length to longer would seem unlikely. |
1666 | | */ |
1667 | | static int ech_decode_inner(SSL_CONNECTION *s, const unsigned char *ob, |
1668 | | size_t ob_len, unsigned char *encoded_inner, |
1669 | | size_t encoded_inner_len) |
1670 | 0 | { |
1671 | 0 | int rv = 0; |
1672 | 0 | PACKET ei; /* encoded inner */ |
1673 | 0 | BUF_MEM *di_mem = NULL; |
1674 | 0 | uint16_t outers[OSSL_ECH_OUTERS_MAX]; /* compressed extension types */ |
1675 | 0 | size_t n_outers = 0; |
1676 | 0 | WPACKET di = { 0 }; /* "fake" pkt for inner */ |
1677 | |
|
1678 | 0 | if (encoded_inner == NULL || ob == NULL || ob_len == 0) { |
1679 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1680 | 0 | return 0; |
1681 | 0 | } |
1682 | 0 | if ((di_mem = BUF_MEM_new()) == NULL |
1683 | 0 | || !BUF_MEM_grow(di_mem, SSL3_RT_MAX_PLAIN_LENGTH) |
1684 | 0 | || !WPACKET_init(&di, di_mem) |
1685 | 0 | || !WPACKET_put_bytes_u8(&di, SSL3_MT_CLIENT_HELLO) |
1686 | 0 | || !WPACKET_start_sub_packet_u24(&di) |
1687 | 0 | || !PACKET_buf_init(&ei, encoded_inner, encoded_inner_len)) { |
1688 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1689 | 0 | goto err; |
1690 | 0 | } |
1691 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1692 | 0 | memset(outers, -1, sizeof(outers)); /* fill with known values for debug */ |
1693 | 0 | #endif |
1694 | | |
1695 | | /* 1. check for outers and make initial checks of those */ |
1696 | 0 | if (ech_find_outers(s, &ei, outers, &n_outers) != 1) |
1697 | 0 | goto err; /* SSLfatal called already */ |
1698 | | |
1699 | | /* 2. reconstitute inner CH */ |
1700 | | /* reset ei */ |
1701 | 0 | if (PACKET_buf_init(&ei, encoded_inner, encoded_inner_len) != 1) { |
1702 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1703 | 0 | goto err; |
1704 | 0 | } |
1705 | 0 | if (ech_reconstitute_inner(s, &di, &ei, ob, ob_len, outers, n_outers) != 1) |
1706 | 0 | goto err; /* SSLfatal called already */ |
1707 | | /* 3. store final inner CH in connection */ |
1708 | 0 | WPACKET_close(&di); |
1709 | 0 | if (!WPACKET_get_length(&di, &s->ext.ech.innerch_len)) { |
1710 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1711 | 0 | goto err; |
1712 | 0 | } |
1713 | 0 | OPENSSL_free(s->ext.ech.innerch); |
1714 | 0 | s->ext.ech.innerch = (unsigned char *)di_mem->data; |
1715 | 0 | di_mem->data = NULL; |
1716 | 0 | rv = 1; |
1717 | 0 | err: |
1718 | 0 | WPACKET_cleanup(&di); |
1719 | 0 | BUF_MEM_free(di_mem); |
1720 | 0 | return rv; |
1721 | 0 | } |
1722 | | |
1723 | | /* |
1724 | | * wrapper for hpke_dec just to save code repetition |
1725 | | * ee is the selected ECH_STORE entry |
1726 | | * the_ech is the value sent by the client |
1727 | | * aad_len is the length of the AAD to use |
1728 | | * aad is the AAD to use |
1729 | | * forhrr is 0 if not hrr, 1 if this is for 2nd CH |
1730 | | * innerlen points to the size of the recovered plaintext |
1731 | | * return pointer to plaintext or NULL (if error) |
1732 | | * |
1733 | | * The plaintext returned is allocated here and must |
1734 | | * be freed by the caller later. |
1735 | | */ |
1736 | | static unsigned char *hpke_decrypt_encch(SSL_CONNECTION *s, |
1737 | | OSSL_ECHSTORE_ENTRY *ee, |
1738 | | OSSL_ECH_ENCCH *the_ech, |
1739 | | size_t aad_len, unsigned char *aad, |
1740 | | int forhrr, size_t *innerlen) |
1741 | 0 | { |
1742 | 0 | size_t cipherlen = 0; |
1743 | 0 | unsigned char *cipher = NULL; |
1744 | 0 | size_t senderpublen = 0; |
1745 | 0 | unsigned char *senderpub = NULL; |
1746 | 0 | size_t clearlen = 0; |
1747 | 0 | unsigned char *clear = NULL; |
1748 | 0 | int hpke_mode = OSSL_HPKE_MODE_BASE; |
1749 | 0 | OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT; |
1750 | 0 | unsigned char info[OSSL_ECH_MAX_INFO_LEN]; |
1751 | 0 | size_t info_len = OSSL_ECH_MAX_INFO_LEN; |
1752 | 0 | int rv = 0; |
1753 | 0 | OSSL_HPKE_CTX *hctx = NULL; |
1754 | 0 | SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); |
1755 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1756 | 0 | size_t publen = 0; |
1757 | 0 | unsigned char *pub = NULL; |
1758 | 0 | #endif |
1759 | |
|
1760 | 0 | if (ee == NULL || ee->nsuites == 0) |
1761 | 0 | return NULL; |
1762 | 0 | cipherlen = the_ech->payload_len; |
1763 | 0 | cipher = the_ech->payload; |
1764 | 0 | senderpublen = the_ech->enc_len; |
1765 | 0 | senderpub = the_ech->enc; |
1766 | 0 | hpke_suite.aead_id = the_ech->aead_id; |
1767 | 0 | hpke_suite.kdf_id = the_ech->kdf_id; |
1768 | 0 | clearlen = cipherlen; /* small overestimate */ |
1769 | 0 | clear = OPENSSL_malloc(clearlen); |
1770 | 0 | if (clear == NULL) |
1771 | 0 | return NULL; |
1772 | | /* The kem_id will be the same for all suites in the entry */ |
1773 | 0 | hpke_suite.kem_id = ee->suites[0].kem_id; |
1774 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1775 | 0 | publen = ee->pub_len; |
1776 | 0 | pub = ee->pub; |
1777 | 0 | ossl_ech_pbuf("aad", aad, aad_len); |
1778 | 0 | ossl_ech_pbuf("my local pub", pub, publen); |
1779 | 0 | ossl_ech_pbuf("senderpub", senderpub, senderpublen); |
1780 | 0 | ossl_ech_pbuf("cipher", cipher, cipherlen); |
1781 | 0 | #endif |
1782 | 0 | if (ossl_ech_make_enc_info(ee->encoded, ee->encoded_len, |
1783 | 0 | info, &info_len) |
1784 | 0 | != 1) { |
1785 | 0 | OPENSSL_free(clear); |
1786 | 0 | return NULL; |
1787 | 0 | } |
1788 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1789 | 0 | ossl_ech_pbuf("info", info, info_len); |
1790 | 0 | #endif |
1791 | 0 | OSSL_TRACE_BEGIN(TLS) |
1792 | 0 | { |
1793 | 0 | BIO_printf(trc_out, |
1794 | 0 | "hpke_dec suite: kem: %04x, kdf: %04x, aead: %04x\n", |
1795 | 0 | hpke_suite.kem_id, hpke_suite.kdf_id, hpke_suite.aead_id); |
1796 | 0 | } |
1797 | 0 | OSSL_TRACE_END(TLS); |
1798 | | /* |
1799 | | * We may generate externally visible OpenSSL errors |
1800 | | * if decryption fails (which is normal) but we'll |
1801 | | * ignore those as we might be dealing with a GREASEd |
1802 | | * ECH. To do that we need to now ignore some errors |
1803 | | * so we use ERR_set_mark() then later ERR_pop_to_mark(). |
1804 | | */ |
1805 | 0 | ERR_set_mark(); |
1806 | | /* Use OSSL_HPKE_* APIs */ |
1807 | 0 | hctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, OSSL_HPKE_ROLE_RECEIVER, |
1808 | 0 | sctx->libctx, sctx->propq); |
1809 | 0 | if (hctx == NULL) |
1810 | 0 | goto clearerrs; |
1811 | 0 | rv = OSSL_HPKE_decap(hctx, senderpub, senderpublen, ee->keyshare, |
1812 | 0 | info, info_len); |
1813 | 0 | if (rv != 1) |
1814 | 0 | goto clearerrs; |
1815 | 0 | if (forhrr == 1) { |
1816 | 0 | rv = OSSL_HPKE_CTX_set_seq(hctx, 1); |
1817 | 0 | if (rv != 1) { |
1818 | | /* don't clear this error - GREASE can't cause it */ |
1819 | 0 | ERR_clear_last_mark(); |
1820 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
1821 | 0 | goto end; |
1822 | 0 | } |
1823 | 0 | } |
1824 | 0 | rv = OSSL_HPKE_open(hctx, clear, &clearlen, aad, aad_len, |
1825 | 0 | cipher, cipherlen); |
1826 | 0 | clearerrs: |
1827 | | /* close off our error handling */ |
1828 | 0 | ERR_pop_to_mark(); |
1829 | 0 | end: |
1830 | 0 | OSSL_HPKE_CTX_free(hctx); |
1831 | 0 | if (rv != 1) { |
1832 | 0 | OSSL_TRACE(TLS, "HPKE decryption failed somehow\n"); |
1833 | 0 | OPENSSL_free(clear); |
1834 | 0 | return NULL; |
1835 | 0 | } |
1836 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1837 | 0 | ossl_ech_pbuf("padded clear", clear, clearlen); |
1838 | 0 | #endif |
1839 | | /* we need to remove possible (actually, v. likely) padding */ |
1840 | 0 | *innerlen = clearlen; |
1841 | 0 | if (ee->version == OSSL_ECH_RFC9849_VERSION) { |
1842 | | /* draft-13 pads after the encoded CH with zeros */ |
1843 | 0 | size_t extsoffset = 0; |
1844 | 0 | size_t extslen = 0; |
1845 | 0 | size_t ch_len = 0; |
1846 | 0 | size_t startofsessid = 0; |
1847 | 0 | size_t echoffset = 0; /* offset of start of ECH within CH */ |
1848 | 0 | uint16_t echtype = OSSL_ECH_type_unknown; /* type of ECH seen */ |
1849 | 0 | size_t outersnioffset = 0; /* offset to SNI in outer */ |
1850 | 0 | int innerflag = -1; |
1851 | 0 | PACKET innerchpkt; |
1852 | |
|
1853 | 0 | if (PACKET_buf_init(&innerchpkt, clear, clearlen) != 1) { |
1854 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1855 | 0 | goto paderr; |
1856 | 0 | } |
1857 | | /* reset the offsets, as we move from outer to inner CH */ |
1858 | 0 | s->ext.ech.ch_offsets_done = 0; |
1859 | 0 | rv = ossl_ech_get_ch_offsets(s, &innerchpkt, &startofsessid, |
1860 | 0 | &extsoffset, &echoffset, &echtype, |
1861 | 0 | &innerflag, &outersnioffset); |
1862 | 0 | if (rv != 1) { |
1863 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1864 | 0 | goto paderr; |
1865 | 0 | } |
1866 | | /* odd form of check below just for emphasis */ |
1867 | 0 | if ((extsoffset + 1) > clearlen) { |
1868 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1869 | 0 | goto paderr; |
1870 | 0 | } |
1871 | 0 | extslen = (unsigned char)(clear[extsoffset]) * 256 |
1872 | 0 | + (unsigned char)(clear[extsoffset + 1]); |
1873 | 0 | ch_len = extsoffset + 2 + extslen; |
1874 | | /* the check below protects us from bogus data */ |
1875 | 0 | if (ch_len > clearlen) { |
1876 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1877 | 0 | goto paderr; |
1878 | 0 | } |
1879 | | /* |
1880 | | * The RFC calls for that padding to be all zeros. I'm not so |
1881 | | * keen on that being a good idea to enforce, so we'll make it |
1882 | | * easy to not do so (but check by default) |
1883 | | */ |
1884 | 0 | #define CHECKZEROS |
1885 | 0 | #ifdef CHECKZEROS |
1886 | 0 | { |
1887 | 0 | size_t zind = 0; |
1888 | |
|
1889 | 0 | if (*innerlen < ch_len) |
1890 | 0 | goto paderr; |
1891 | 0 | for (zind = ch_len; zind != *innerlen; zind++) { |
1892 | 0 | if (clear[zind] != 0x00) |
1893 | 0 | goto paderr; |
1894 | 0 | } |
1895 | 0 | } |
1896 | 0 | #endif |
1897 | 0 | *innerlen = ch_len; |
1898 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
1899 | 0 | ossl_ech_pbuf("unpadded clear", clear, *innerlen); |
1900 | 0 | #endif |
1901 | 0 | return clear; |
1902 | 0 | } |
1903 | 0 | paderr: |
1904 | 0 | OPENSSL_free(clear); |
1905 | 0 | return NULL; |
1906 | 0 | } |
1907 | | |
1908 | | /* |
1909 | | * If an ECH is present, attempt decryption |
1910 | | * outerpkt is the packet with the outer CH |
1911 | | * newpkt is the packet with the decrypted inner CH |
1912 | | * return 1 for success, other otherwise |
1913 | | * |
1914 | | * If decryption succeeds, the caller can swap the inner and outer |
1915 | | * CHs so that all further processing will only take into account |
1916 | | * the inner CH. |
1917 | | * |
1918 | | * The fact that decryption worked is signalled to the caller |
1919 | | * via s->ext.ech.success |
1920 | | * |
1921 | | * This function is called early, (hence the name:-), before |
1922 | | * the outer CH decoding has really started, so we need to be |
1923 | | * careful peeking into the packet |
1924 | | * |
1925 | | * The plan: |
1926 | | * 1. check if there's an ECH |
1927 | | * 2. trial-decrypt or check if config matches one loaded |
1928 | | * 3. if decrypt fails tee-up GREASE |
1929 | | * 4. if decrypt worked, decode and de-compress cleartext to |
1930 | | * make up real inner CH for later processing |
1931 | | */ |
1932 | | int ossl_ech_early_decrypt(SSL_CONNECTION *s, PACKET *outerpkt, PACKET *newpkt) |
1933 | 0 | { |
1934 | 0 | int num = 0, cfgind = -1, foundcfg = 0, forhrr = 0, innerflag = -1; |
1935 | 0 | OSSL_ECH_ENCCH *extval = NULL; |
1936 | 0 | PACKET echpkt; |
1937 | 0 | const unsigned char *startofech = NULL, *opd = NULL; |
1938 | 0 | size_t echlen = 0, clearlen = 0, aad_len = 0; |
1939 | 0 | unsigned char *clear = NULL, *aad = NULL; |
1940 | | /* offsets of things within CH */ |
1941 | 0 | size_t startofsessid = 0, startofexts = 0, echoffset = 0, opl = 0; |
1942 | 0 | size_t outersnioffset = 0, startofciphertext = 0, lenofciphertext = 0; |
1943 | 0 | uint16_t echtype = OSSL_ECH_type_unknown; /* type of ECH seen */ |
1944 | 0 | char *osni_str = NULL; |
1945 | 0 | OSSL_ECHSTORE *es = NULL; |
1946 | 0 | OSSL_ECHSTORE_ENTRY *ee = NULL; |
1947 | |
|
1948 | 0 | if (s == NULL) |
1949 | 0 | return 0; |
1950 | 0 | if (outerpkt == NULL || newpkt == NULL) { |
1951 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1952 | 0 | return 0; |
1953 | 0 | } |
1954 | | /* find offsets - on success, outputs are safe to use */ |
1955 | 0 | if (ossl_ech_get_ch_offsets(s, outerpkt, &startofsessid, &startofexts, |
1956 | 0 | &echoffset, &echtype, &innerflag, |
1957 | 0 | &outersnioffset) |
1958 | 0 | != 1) { |
1959 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1960 | 0 | return 0; |
1961 | 0 | } |
1962 | 0 | if (echoffset == 0 || echtype != TLSEXT_TYPE_ech) |
1963 | 0 | return 1; /* ECH not present or wrong version */ |
1964 | 0 | if (innerflag == 1) { |
1965 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1966 | 0 | return 0; |
1967 | 0 | } |
1968 | 0 | s->ext.ech.attempted = 1; /* Remember that we got an ECH */ |
1969 | 0 | s->ext.ech.attempted_type = echtype; |
1970 | 0 | if (s->hello_retry_request == SSL_HRR_PENDING) |
1971 | 0 | forhrr = 1; /* set forhrr if that's correct */ |
1972 | 0 | opl = PACKET_remaining(outerpkt); |
1973 | 0 | opd = PACKET_data(outerpkt); |
1974 | 0 | s->tmp_session_id_len = opd[startofsessid]; /* grab the session id */ |
1975 | 0 | if (s->tmp_session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH |
1976 | 0 | || startofsessid + 1 + s->tmp_session_id_len > opl) { |
1977 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1978 | 0 | goto err; |
1979 | 0 | } |
1980 | 0 | memcpy(s->tmp_session_id, &opd[startofsessid + 1], s->tmp_session_id_len); |
1981 | 0 | if (outersnioffset > 0) { /* Grab the outer SNI for tracing */ |
1982 | 0 | if (ech_get_outer_sni(s, &osni_str, opd, opl, outersnioffset) != 1 |
1983 | 0 | || osni_str == NULL) { |
1984 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1985 | 0 | goto err; |
1986 | 0 | } |
1987 | 0 | OSSL_TRACE1(TLS, "EARLY: outer SNI of %s\n", osni_str); |
1988 | 0 | } else { |
1989 | 0 | OSSL_TRACE(TLS, "EARLY: no sign of an outer SNI\n"); |
1990 | 0 | } |
1991 | 0 | if (echoffset > opl - 4) { |
1992 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1993 | 0 | goto err; |
1994 | 0 | } |
1995 | 0 | startofech = &opd[echoffset + 4]; |
1996 | 0 | echlen = opd[echoffset + 2] * 256 + opd[echoffset + 3]; |
1997 | 0 | if (echlen > opl - echoffset - 4) { |
1998 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
1999 | 0 | goto err; |
2000 | 0 | } |
2001 | 0 | if (PACKET_buf_init(&echpkt, startofech, echlen) != 1) { |
2002 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
2003 | 0 | goto err; |
2004 | 0 | } |
2005 | 0 | if (ech_decode_inbound_ech(s, &echpkt, &extval, &startofciphertext) != 1) |
2006 | 0 | goto err; /* SSLfatal already called if needed */ |
2007 | | /* |
2008 | | * startofciphertext is within the ECH value and after the length of the |
2009 | | * ciphertext, so we need to bump it by the offset of ECH within the CH |
2010 | | * plus the ECH type (2 octets) and length (also 2 octets) and that |
2011 | | * ciphertext length (another 2 octets) for a total of 6 octets |
2012 | | */ |
2013 | 0 | startofciphertext += echoffset + 6; |
2014 | 0 | lenofciphertext = extval->payload_len; |
2015 | 0 | aad_len = opl; |
2016 | 0 | if (aad_len < startofciphertext + lenofciphertext) { |
2017 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
2018 | 0 | goto err; |
2019 | 0 | } |
2020 | 0 | aad = OPENSSL_memdup(opd, aad_len); |
2021 | 0 | if (aad == NULL) { |
2022 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
2023 | 0 | goto err; |
2024 | 0 | } |
2025 | 0 | memset(aad + startofciphertext, 0, lenofciphertext); |
2026 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
2027 | 0 | ossl_ech_pbuf("EARLY aad", aad, aad_len); |
2028 | 0 | #endif |
2029 | 0 | s->ext.ech.grease = OSSL_ECH_GREASE_UNKNOWN; |
2030 | 0 | if (s->ext.ech.es == NULL) { |
2031 | 0 | SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION); |
2032 | 0 | goto err; |
2033 | 0 | } |
2034 | 0 | es = s->ext.ech.es; |
2035 | 0 | num = (es == NULL || es->entries == NULL ? 0 |
2036 | 0 | : sk_OSSL_ECHSTORE_ENTRY_num(es->entries)); |
2037 | 0 | for (cfgind = 0; cfgind != num; cfgind++) { |
2038 | 0 | ee = sk_OSSL_ECHSTORE_ENTRY_value(es->entries, cfgind); |
2039 | 0 | OSSL_TRACE_BEGIN(TLS) |
2040 | 0 | { |
2041 | 0 | BIO_printf(trc_out, |
2042 | 0 | "EARLY: rx'd config id (%x) ==? %d-th configured (%x)\n", |
2043 | 0 | extval->config_id, cfgind, ee->config_id); |
2044 | 0 | } |
2045 | 0 | OSSL_TRACE_END(TLS); |
2046 | 0 | if (extval->config_id == ee->config_id) { |
2047 | 0 | foundcfg = 1; |
2048 | 0 | break; |
2049 | 0 | } |
2050 | 0 | } |
2051 | 0 | if (foundcfg == 1) { |
2052 | 0 | clear = hpke_decrypt_encch(s, ee, extval, aad_len, aad, |
2053 | 0 | forhrr, &clearlen); |
2054 | 0 | if (clear == NULL) |
2055 | 0 | s->ext.ech.grease = OSSL_ECH_IS_GREASE; |
2056 | 0 | } |
2057 | | /* if still needed, trial decryptions */ |
2058 | 0 | if (clear == NULL && (s->options & SSL_OP_ECH_TRIALDECRYPT)) { |
2059 | 0 | foundcfg = 0; /* reset as we're trying again */ |
2060 | 0 | for (cfgind = 0; cfgind != num; cfgind++) { |
2061 | 0 | ee = sk_OSSL_ECHSTORE_ENTRY_value(es->entries, cfgind); |
2062 | 0 | clear = hpke_decrypt_encch(s, ee, extval, |
2063 | 0 | aad_len, aad, forhrr, &clearlen); |
2064 | 0 | if (clear != NULL) { |
2065 | 0 | foundcfg = 1; |
2066 | 0 | s->ext.ech.grease = OSSL_ECH_NOT_GREASE; |
2067 | 0 | break; |
2068 | 0 | } |
2069 | 0 | } |
2070 | 0 | } |
2071 | 0 | OPENSSL_free(aad); |
2072 | 0 | aad = NULL; |
2073 | 0 | s->ext.ech.done = 1; /* decrypting worked or not, but we're done now */ |
2074 | 0 | s->ext.ech.grease = OSSL_ECH_IS_GREASE; /* if decrypt fails tee-up GREASE */ |
2075 | 0 | s->ext.ech.success = 0; |
2076 | 0 | if (clear != NULL) { |
2077 | 0 | s->ext.ech.grease = OSSL_ECH_NOT_GREASE; |
2078 | 0 | s->ext.ech.success = 1; |
2079 | 0 | } |
2080 | 0 | OSSL_TRACE_BEGIN(TLS) |
2081 | 0 | { |
2082 | 0 | BIO_printf(trc_out, "EARLY: success: %d, assume_grease: %d, " |
2083 | 0 | "foundcfg: %d, cfgind: %d, clearlen: %zd, clear %p\n", |
2084 | 0 | s->ext.ech.success, s->ext.ech.grease, foundcfg, |
2085 | 0 | cfgind, clearlen, (void *)clear); |
2086 | 0 | } |
2087 | 0 | OSSL_TRACE_END(TLS); |
2088 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
2089 | 0 | if (foundcfg == 1 && clear != NULL) { /* Bit more logging */ |
2090 | 0 | ossl_ech_pbuf("local config_id", &ee->config_id, 1); |
2091 | 0 | ossl_ech_pbuf("remote config_id", &extval->config_id, 1); |
2092 | 0 | ossl_ech_pbuf("clear", clear, clearlen); |
2093 | 0 | } |
2094 | 0 | #endif |
2095 | 0 | ossl_ech_encch_free(extval); |
2096 | 0 | OPENSSL_free(extval); |
2097 | 0 | extval = NULL; |
2098 | 0 | if (s->ext.ech.grease == OSSL_ECH_IS_GREASE) { |
2099 | 0 | OPENSSL_free(clear); |
2100 | 0 | return 1; |
2101 | 0 | } |
2102 | | /* 4. if decrypt worked, de-compress cleartext to make up real inner CH */ |
2103 | 0 | if (ech_decode_inner(s, opd, opl, clear, clearlen) != 1) { |
2104 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
2105 | 0 | goto err; |
2106 | 0 | } |
2107 | 0 | OPENSSL_free(clear); |
2108 | 0 | clear = NULL; |
2109 | 0 | #ifdef OSSL_ECH_SUPERVERBOSE |
2110 | 0 | ossl_ech_pbuf("Inner CH (decoded)", s->ext.ech.innerch, |
2111 | 0 | s->ext.ech.innerch_len); |
2112 | 0 | #endif |
2113 | 0 | if (PACKET_buf_init(newpkt, s->ext.ech.innerch, |
2114 | 0 | s->ext.ech.innerch_len) |
2115 | 0 | != 1) { |
2116 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
2117 | 0 | goto err; |
2118 | 0 | } |
2119 | | /* tls_process_client_hello doesn't want the message header, so skip it */ |
2120 | 0 | if (!PACKET_forward(newpkt, SSL3_HM_HEADER_LENGTH)) { |
2121 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
2122 | 0 | goto err; |
2123 | 0 | } |
2124 | 0 | if (ossl_ech_intbuf_add(s, s->ext.ech.innerch, |
2125 | 0 | s->ext.ech.innerch_len, 0) |
2126 | 0 | != 1) { |
2127 | 0 | SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); |
2128 | 0 | goto err; |
2129 | 0 | } |
2130 | 0 | return 1; |
2131 | 0 | err: |
2132 | 0 | OPENSSL_free(aad); |
2133 | 0 | if (extval != NULL) { |
2134 | 0 | ossl_ech_encch_free(extval); |
2135 | 0 | OPENSSL_free(extval); |
2136 | 0 | } |
2137 | 0 | OPENSSL_free(clear); |
2138 | 0 | return 0; |
2139 | 0 | } |
2140 | | |
2141 | | int ossl_ech_intbuf_add(SSL_CONNECTION *s, const unsigned char *buf, |
2142 | | size_t blen, int hash_existing) |
2143 | 0 | { |
2144 | 0 | EVP_MD_CTX *ctx = NULL; |
2145 | 0 | EVP_MD *md = NULL; |
2146 | 0 | unsigned int rv = 0, hashlen = 0; |
2147 | 0 | unsigned char hashval[EVP_MAX_MD_SIZE], *t1; |
2148 | 0 | size_t tlen; |
2149 | 0 | WPACKET tpkt = { 0 }; |
2150 | 0 | BUF_MEM *tpkt_mem = NULL; |
2151 | |
|
2152 | 0 | if (s == NULL || buf == NULL || blen == 0) |
2153 | 0 | goto err; |
2154 | 0 | if (hash_existing == 1) { |
2155 | | /* hash existing buffer, needed during HRR */ |
2156 | 0 | if (s->ext.ech.transbuf == NULL |
2157 | 0 | || (md = (EVP_MD *)ssl_handshake_md(s)) == NULL |
2158 | 0 | || (ctx = EVP_MD_CTX_new()) == NULL |
2159 | 0 | || EVP_DigestInit_ex(ctx, md, NULL) <= 0 |
2160 | 0 | || EVP_DigestUpdate(ctx, s->ext.ech.transbuf, |
2161 | 0 | s->ext.ech.transbuf_len) |
2162 | 0 | <= 0 |
2163 | 0 | || EVP_DigestFinal_ex(ctx, hashval, &hashlen) <= 0 |
2164 | 0 | || (tpkt_mem = BUF_MEM_new()) == NULL |
2165 | 0 | || !WPACKET_init(&tpkt, tpkt_mem) |
2166 | 0 | || !WPACKET_put_bytes_u8(&tpkt, SSL3_MT_MESSAGE_HASH) |
2167 | 0 | || !WPACKET_put_bytes_u24(&tpkt, hashlen) |
2168 | 0 | || !WPACKET_memcpy(&tpkt, hashval, hashlen) |
2169 | 0 | || !WPACKET_get_length(&tpkt, &tlen) |
2170 | 0 | || (t1 = OPENSSL_realloc(s->ext.ech.transbuf, tlen + blen)) == NULL) |
2171 | 0 | goto err; |
2172 | 0 | s->ext.ech.transbuf = t1; |
2173 | 0 | memcpy(s->ext.ech.transbuf, tpkt_mem->data, tlen); |
2174 | 0 | memcpy(s->ext.ech.transbuf + tlen, buf, blen); |
2175 | 0 | s->ext.ech.transbuf_len = tlen + blen; |
2176 | 0 | } else { |
2177 | | /* just add new octets */ |
2178 | 0 | if ((t1 = OPENSSL_realloc(s->ext.ech.transbuf, |
2179 | 0 | s->ext.ech.transbuf_len + blen)) |
2180 | 0 | == NULL) |
2181 | 0 | goto err; |
2182 | 0 | s->ext.ech.transbuf = t1; |
2183 | 0 | memcpy(s->ext.ech.transbuf + s->ext.ech.transbuf_len, buf, blen); |
2184 | 0 | s->ext.ech.transbuf_len += blen; |
2185 | 0 | } |
2186 | 0 | rv = 1; |
2187 | 0 | err: |
2188 | 0 | BUF_MEM_free(tpkt_mem); |
2189 | 0 | WPACKET_cleanup(&tpkt); |
2190 | 0 | EVP_MD_CTX_free(ctx); |
2191 | 0 | return rv; |
2192 | 0 | } |
2193 | | |
2194 | | int ossl_ech_intbuf_fetch(SSL_CONNECTION *s, unsigned char **buf, size_t *blen) |
2195 | 0 | { |
2196 | 0 | if (s == NULL || buf == NULL || blen == NULL || s->ext.ech.transbuf == NULL) |
2197 | 0 | return 0; |
2198 | 0 | *buf = s->ext.ech.transbuf; |
2199 | 0 | *blen = s->ext.ech.transbuf_len; |
2200 | 0 | return 1; |
2201 | 0 | } |
2202 | | |
2203 | | int ossl_ech_stash_keyshares(SSL_CONNECTION *s) |
2204 | 0 | { |
2205 | 0 | size_t i; |
2206 | |
|
2207 | 0 | ech_free_stashed_key_shares(&s->ext.ech); |
2208 | 0 | for (i = 0; i != s->s3.tmp.num_ks_pkey; i++) { |
2209 | 0 | s->ext.ech.ks_pkey[i] = s->s3.tmp.ks_pkey[i]; |
2210 | 0 | if (EVP_PKEY_up_ref(s->ext.ech.ks_pkey[i]) != 1) |
2211 | 0 | return 0; |
2212 | 0 | s->ext.ech.ks_group_id[i] = s->s3.tmp.ks_group_id[i]; |
2213 | 0 | } |
2214 | 0 | s->ext.ech.num_ks_pkey = s->s3.tmp.num_ks_pkey; |
2215 | 0 | return 1; |
2216 | 0 | } |
2217 | | |
2218 | | int ossl_ech_unstash_keyshares(SSL_CONNECTION *s) |
2219 | 0 | { |
2220 | 0 | size_t i; |
2221 | |
|
2222 | 0 | for (i = 0; i != s->s3.tmp.num_ks_pkey; i++) { |
2223 | 0 | EVP_PKEY_free(s->s3.tmp.ks_pkey[i]); |
2224 | 0 | s->s3.tmp.ks_pkey[i] = NULL; |
2225 | 0 | } |
2226 | 0 | for (i = 0; i != s->ext.ech.num_ks_pkey; i++) { |
2227 | 0 | s->s3.tmp.ks_pkey[i] = s->ext.ech.ks_pkey[i]; |
2228 | 0 | if (EVP_PKEY_up_ref(s->s3.tmp.ks_pkey[i]) != 1) |
2229 | 0 | return 0; |
2230 | 0 | s->s3.tmp.ks_group_id[i] = s->ext.ech.ks_group_id[i]; |
2231 | 0 | } |
2232 | 0 | s->s3.tmp.num_ks_pkey = s->ext.ech.num_ks_pkey; |
2233 | 0 | ech_free_stashed_key_shares(&s->ext.ech); |
2234 | 0 | return 1; |
2235 | 0 | } |
2236 | | #endif |