1 /* Copyright (c) 2021, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/ssl.h>
16
17 #include <assert.h>
18 #include <string.h>
19
20 #include <algorithm>
21 #include <utility>
22
23 #include <openssl/aead.h>
24 #include <openssl/bytestring.h>
25 #include <openssl/curve25519.h>
26 #include <openssl/err.h>
27 #include <openssl/hkdf.h>
28 #include <openssl/hpke.h>
29 #include <openssl/rand.h>
30
31 #include "internal.h"
32
33
34 BSSL_NAMESPACE_BEGIN
35
36 // ECH reuses the extension code point for the version number.
37 static constexpr uint16_t kECHConfigVersion =
38 TLSEXT_TYPE_encrypted_client_hello;
39
40 static const decltype(&EVP_hpke_aes_128_gcm) kSupportedAEADs[] = {
41 &EVP_hpke_aes_128_gcm,
42 &EVP_hpke_aes_256_gcm,
43 &EVP_hpke_chacha20_poly1305,
44 };
45
get_ech_aead(uint16_t aead_id)46 static const EVP_HPKE_AEAD *get_ech_aead(uint16_t aead_id) {
47 for (const auto aead_func : kSupportedAEADs) {
48 const EVP_HPKE_AEAD *aead = aead_func();
49 if (aead_id == EVP_HPKE_AEAD_id(aead)) {
50 return aead;
51 }
52 }
53 return nullptr;
54 }
55
56 // ssl_client_hello_write_without_extensions serializes |client_hello| into
57 // |out|, omitting the length-prefixed extensions. It serializes individual
58 // fields, starting with |client_hello->version|, and ignores the
59 // |client_hello->client_hello| field. It returns true on success and false on
60 // failure.
ssl_client_hello_write_without_extensions(const SSL_CLIENT_HELLO * client_hello,CBB * out)61 static bool ssl_client_hello_write_without_extensions(
62 const SSL_CLIENT_HELLO *client_hello, CBB *out) {
63 CBB cbb;
64 if (!CBB_add_u16(out, client_hello->version) ||
65 !CBB_add_bytes(out, client_hello->random, client_hello->random_len) ||
66 !CBB_add_u8_length_prefixed(out, &cbb) ||
67 !CBB_add_bytes(&cbb, client_hello->session_id,
68 client_hello->session_id_len) ||
69 !CBB_add_u16_length_prefixed(out, &cbb) ||
70 !CBB_add_bytes(&cbb, client_hello->cipher_suites,
71 client_hello->cipher_suites_len) ||
72 !CBB_add_u8_length_prefixed(out, &cbb) ||
73 !CBB_add_bytes(&cbb, client_hello->compression_methods,
74 client_hello->compression_methods_len) ||
75 !CBB_flush(out)) {
76 return false;
77 }
78 return true;
79 }
80
is_valid_client_hello_inner(SSL * ssl,uint8_t * out_alert,Span<const uint8_t> body)81 static bool is_valid_client_hello_inner(SSL *ssl, uint8_t *out_alert,
82 Span<const uint8_t> body) {
83 // See draft-ietf-tls-esni-13, section 7.1.
84 SSL_CLIENT_HELLO client_hello;
85 CBS extension;
86 if (!ssl_client_hello_init(ssl, &client_hello, body) ||
87 !ssl_client_hello_get_extension(&client_hello, &extension,
88 TLSEXT_TYPE_encrypted_client_hello) ||
89 CBS_len(&extension) != 1 || //
90 CBS_data(&extension)[0] != ECH_CLIENT_INNER ||
91 !ssl_client_hello_get_extension(&client_hello, &extension,
92 TLSEXT_TYPE_supported_versions)) {
93 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
94 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CLIENT_HELLO_INNER);
95 return false;
96 }
97 // Parse supported_versions and reject TLS versions prior to TLS 1.3. Older
98 // versions are incompatible with ECH.
99 CBS versions;
100 if (!CBS_get_u8_length_prefixed(&extension, &versions) ||
101 CBS_len(&extension) != 0 || //
102 CBS_len(&versions) == 0) {
103 *out_alert = SSL_AD_DECODE_ERROR;
104 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
105 return false;
106 }
107 while (CBS_len(&versions) != 0) {
108 uint16_t version;
109 if (!CBS_get_u16(&versions, &version)) {
110 *out_alert = SSL_AD_DECODE_ERROR;
111 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
112 return false;
113 }
114 if (version == SSL3_VERSION || version == TLS1_VERSION ||
115 version == TLS1_1_VERSION || version == TLS1_2_VERSION ||
116 version == DTLS1_VERSION || version == DTLS1_2_VERSION) {
117 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
118 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CLIENT_HELLO_INNER);
119 return false;
120 }
121 }
122 return true;
123 }
124
ssl_decode_client_hello_inner(SSL * ssl,uint8_t * out_alert,Array<uint8_t> * out_client_hello_inner,Span<const uint8_t> encoded_client_hello_inner,const SSL_CLIENT_HELLO * client_hello_outer)125 bool ssl_decode_client_hello_inner(
126 SSL *ssl, uint8_t *out_alert, Array<uint8_t> *out_client_hello_inner,
127 Span<const uint8_t> encoded_client_hello_inner,
128 const SSL_CLIENT_HELLO *client_hello_outer) {
129 SSL_CLIENT_HELLO client_hello_inner;
130 CBS cbs = encoded_client_hello_inner;
131 if (!ssl_parse_client_hello_with_trailing_data(ssl, &cbs,
132 &client_hello_inner)) {
133 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
134 return false;
135 }
136 // The remaining data is padding.
137 uint8_t padding;
138 while (CBS_get_u8(&cbs, &padding)) {
139 if (padding != 0) {
140 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
141 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
142 return false;
143 }
144 }
145
146 // TLS 1.3 ClientHellos must have extensions, and EncodedClientHelloInners use
147 // ClientHelloOuter's session_id.
148 if (client_hello_inner.extensions_len == 0 ||
149 client_hello_inner.session_id_len != 0) {
150 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
151 return false;
152 }
153 client_hello_inner.session_id = client_hello_outer->session_id;
154 client_hello_inner.session_id_len = client_hello_outer->session_id_len;
155
156 // Begin serializing a message containing the ClientHelloInner in |cbb|.
157 ScopedCBB cbb;
158 CBB body, extensions_cbb;
159 if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO) ||
160 !ssl_client_hello_write_without_extensions(&client_hello_inner, &body) ||
161 !CBB_add_u16_length_prefixed(&body, &extensions_cbb)) {
162 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
163 return false;
164 }
165
166 auto inner_extensions = MakeConstSpan(client_hello_inner.extensions,
167 client_hello_inner.extensions_len);
168 CBS ext_list_wrapper;
169 if (!ssl_client_hello_get_extension(&client_hello_inner, &ext_list_wrapper,
170 TLSEXT_TYPE_ech_outer_extensions)) {
171 // No ech_outer_extensions. Copy everything.
172 if (!CBB_add_bytes(&extensions_cbb, inner_extensions.data(),
173 inner_extensions.size())) {
174 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
175 return false;
176 }
177 } else {
178 const size_t offset = CBS_data(&ext_list_wrapper) - inner_extensions.data();
179 auto inner_extensions_before =
180 inner_extensions.subspan(0, offset - 4 /* extension header */);
181 auto inner_extensions_after =
182 inner_extensions.subspan(offset + CBS_len(&ext_list_wrapper));
183 if (!CBB_add_bytes(&extensions_cbb, inner_extensions_before.data(),
184 inner_extensions_before.size())) {
185 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
186 return false;
187 }
188
189 // Expand ech_outer_extensions. See draft-ietf-tls-esni-13, Appendix B.
190 CBS ext_list;
191 if (!CBS_get_u8_length_prefixed(&ext_list_wrapper, &ext_list) ||
192 CBS_len(&ext_list) == 0 || CBS_len(&ext_list_wrapper) != 0) {
193 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
194 return false;
195 }
196 CBS outer_extensions;
197 CBS_init(&outer_extensions, client_hello_outer->extensions,
198 client_hello_outer->extensions_len);
199 while (CBS_len(&ext_list) != 0) {
200 // Find the next extension to copy.
201 uint16_t want;
202 if (!CBS_get_u16(&ext_list, &want)) {
203 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
204 return false;
205 }
206 // The ECH extension itself is not in the AAD and may not be referenced.
207 if (want == TLSEXT_TYPE_encrypted_client_hello) {
208 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
209 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_OUTER_EXTENSION);
210 return false;
211 }
212 // Seek to |want| in |outer_extensions|. |ext_list| is required to match
213 // ClientHelloOuter in order.
214 uint16_t found;
215 CBS ext_body;
216 do {
217 if (CBS_len(&outer_extensions) == 0) {
218 *out_alert = SSL_AD_ILLEGAL_PARAMETER;
219 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_OUTER_EXTENSION);
220 return false;
221 }
222 if (!CBS_get_u16(&outer_extensions, &found) ||
223 !CBS_get_u16_length_prefixed(&outer_extensions, &ext_body)) {
224 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
225 return false;
226 }
227 } while (found != want);
228 // Copy the extension.
229 if (!CBB_add_u16(&extensions_cbb, found) ||
230 !CBB_add_u16(&extensions_cbb, CBS_len(&ext_body)) ||
231 !CBB_add_bytes(&extensions_cbb, CBS_data(&ext_body),
232 CBS_len(&ext_body))) {
233 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
234 return false;
235 }
236 }
237
238 if (!CBB_add_bytes(&extensions_cbb, inner_extensions_after.data(),
239 inner_extensions_after.size())) {
240 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
241 return false;
242 }
243 }
244 if (!CBB_flush(&body)) {
245 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
246 return false;
247 }
248
249 if (!is_valid_client_hello_inner(
250 ssl, out_alert, MakeConstSpan(CBB_data(&body), CBB_len(&body)))) {
251 return false;
252 }
253
254 if (!ssl->method->finish_message(ssl, cbb.get(), out_client_hello_inner)) {
255 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
256 return false;
257 }
258 return true;
259 }
260
ssl_client_hello_decrypt(SSL_HANDSHAKE * hs,uint8_t * out_alert,bool * out_is_decrypt_error,Array<uint8_t> * out,const SSL_CLIENT_HELLO * client_hello_outer,Span<const uint8_t> payload)261 bool ssl_client_hello_decrypt(SSL_HANDSHAKE *hs, uint8_t *out_alert,
262 bool *out_is_decrypt_error, Array<uint8_t> *out,
263 const SSL_CLIENT_HELLO *client_hello_outer,
264 Span<const uint8_t> payload) {
265 *out_is_decrypt_error = false;
266
267 // The ClientHelloOuterAAD is |client_hello_outer| with |payload| (which must
268 // point within |client_hello_outer->extensions|) replaced with zeros. See
269 // draft-ietf-tls-esni-13, section 5.2.
270 Array<uint8_t> aad;
271 if (!aad.CopyFrom(MakeConstSpan(client_hello_outer->client_hello,
272 client_hello_outer->client_hello_len))) {
273 *out_alert = SSL_AD_INTERNAL_ERROR;
274 return false;
275 }
276
277 // We assert with |uintptr_t| because the comparison would be UB if they
278 // didn't alias.
279 assert(reinterpret_cast<uintptr_t>(client_hello_outer->extensions) <=
280 reinterpret_cast<uintptr_t>(payload.data()));
281 assert(reinterpret_cast<uintptr_t>(client_hello_outer->extensions +
282 client_hello_outer->extensions_len) >=
283 reinterpret_cast<uintptr_t>(payload.data() + payload.size()));
284 Span<uint8_t> payload_aad = MakeSpan(aad).subspan(
285 payload.data() - client_hello_outer->client_hello, payload.size());
286 OPENSSL_memset(payload_aad.data(), 0, payload_aad.size());
287
288 // Decrypt the EncodedClientHelloInner.
289 Array<uint8_t> encoded;
290 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
291 // In fuzzer mode, disable encryption to improve coverage. We reserve a short
292 // input to signal decryption failure, so the fuzzer can explore fallback to
293 // ClientHelloOuter.
294 const uint8_t kBadPayload[] = {0xff};
295 if (payload == kBadPayload) {
296 *out_alert = SSL_AD_DECRYPT_ERROR;
297 *out_is_decrypt_error = true;
298 OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
299 return false;
300 }
301 if (!encoded.CopyFrom(payload)) {
302 *out_alert = SSL_AD_INTERNAL_ERROR;
303 return false;
304 }
305 #else
306 if (!encoded.Init(payload.size())) {
307 *out_alert = SSL_AD_INTERNAL_ERROR;
308 return false;
309 }
310 size_t len;
311 if (!EVP_HPKE_CTX_open(hs->ech_hpke_ctx.get(), encoded.data(), &len,
312 encoded.size(), payload.data(), payload.size(),
313 aad.data(), aad.size())) {
314 *out_alert = SSL_AD_DECRYPT_ERROR;
315 *out_is_decrypt_error = true;
316 OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
317 return false;
318 }
319 encoded.Shrink(len);
320 #endif
321
322 if (!ssl_decode_client_hello_inner(hs->ssl, out_alert, out, encoded,
323 client_hello_outer)) {
324 return false;
325 }
326
327 ssl_do_msg_callback(hs->ssl, /*is_write=*/0, SSL3_RT_CLIENT_HELLO_INNER,
328 *out);
329 return true;
330 }
331
is_hex_component(Span<const uint8_t> in)332 static bool is_hex_component(Span<const uint8_t> in) {
333 if (in.size() < 2 || in[0] != '0' || (in[1] != 'x' && in[1] != 'X')) {
334 return false;
335 }
336 for (uint8_t b : in.subspan(2)) {
337 if (!OPENSSL_isxdigit(b)) {
338 return false;
339 }
340 }
341 return true;
342 }
343
is_decimal_component(Span<const uint8_t> in)344 static bool is_decimal_component(Span<const uint8_t> in) {
345 if (in.empty()) {
346 return false;
347 }
348 for (uint8_t b : in) {
349 if (!('0' <= b && b <= '9')) {
350 return false;
351 }
352 }
353 return true;
354 }
355
ssl_is_valid_ech_public_name(Span<const uint8_t> public_name)356 bool ssl_is_valid_ech_public_name(Span<const uint8_t> public_name) {
357 // See draft-ietf-tls-esni-13, Section 4 and RFC 5890, Section 2.3.1. The
358 // public name must be a dot-separated sequence of LDH labels and not begin or
359 // end with a dot.
360 auto remaining = public_name;
361 if (remaining.empty()) {
362 return false;
363 }
364 Span<const uint8_t> last;
365 while (!remaining.empty()) {
366 // Find the next dot-separated component.
367 auto dot = std::find(remaining.begin(), remaining.end(), '.');
368 Span<const uint8_t> component;
369 if (dot == remaining.end()) {
370 component = remaining;
371 last = component;
372 remaining = Span<const uint8_t>();
373 } else {
374 component = remaining.subspan(0, dot - remaining.begin());
375 // Skip the dot.
376 remaining = remaining.subspan(dot - remaining.begin() + 1);
377 if (remaining.empty()) {
378 // Trailing dots are not allowed.
379 return false;
380 }
381 }
382 // |component| must be a valid LDH label. Checking for empty components also
383 // rejects leading dots.
384 if (component.empty() || component.size() > 63 ||
385 component.front() == '-' || component.back() == '-') {
386 return false;
387 }
388 for (uint8_t c : component) {
389 if (!OPENSSL_isalnum(c) && c != '-') {
390 return false;
391 }
392 }
393 }
394
395 // The WHATWG URL parser additionally does not allow any DNS names that end in
396 // a numeric component. See:
397 // https://url.spec.whatwg.org/#concept-host-parser
398 // https://url.spec.whatwg.org/#ends-in-a-number-checker
399 //
400 // The WHATWG parser is formulated in terms of parsing decimal, octal, and
401 // hex, along with a separate ASCII digits check. The ASCII digits check
402 // subsumes the decimal and octal check, so we only need to check two cases.
403 return !is_hex_component(last) && !is_decimal_component(last);
404 }
405
parse_ech_config(CBS * cbs,ECHConfig * out,bool * out_supported,bool all_extensions_mandatory)406 static bool parse_ech_config(CBS *cbs, ECHConfig *out, bool *out_supported,
407 bool all_extensions_mandatory) {
408 uint16_t version;
409 CBS orig = *cbs;
410 CBS contents;
411 if (!CBS_get_u16(cbs, &version) ||
412 !CBS_get_u16_length_prefixed(cbs, &contents)) {
413 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
414 return false;
415 }
416
417 if (version != kECHConfigVersion) {
418 *out_supported = false;
419 return true;
420 }
421
422 // Make a copy of the ECHConfig and parse from it, so the results alias into
423 // the saved copy.
424 if (!out->raw.CopyFrom(
425 MakeConstSpan(CBS_data(&orig), CBS_len(&orig) - CBS_len(cbs)))) {
426 return false;
427 }
428
429 CBS ech_config(out->raw);
430 CBS public_name, public_key, cipher_suites, extensions;
431 if (!CBS_skip(&ech_config, 2) || // version
432 !CBS_get_u16_length_prefixed(&ech_config, &contents) ||
433 !CBS_get_u8(&contents, &out->config_id) ||
434 !CBS_get_u16(&contents, &out->kem_id) ||
435 !CBS_get_u16_length_prefixed(&contents, &public_key) ||
436 CBS_len(&public_key) == 0 ||
437 !CBS_get_u16_length_prefixed(&contents, &cipher_suites) ||
438 CBS_len(&cipher_suites) == 0 || CBS_len(&cipher_suites) % 4 != 0 ||
439 !CBS_get_u8(&contents, &out->maximum_name_length) ||
440 !CBS_get_u8_length_prefixed(&contents, &public_name) ||
441 CBS_len(&public_name) == 0 ||
442 !CBS_get_u16_length_prefixed(&contents, &extensions) ||
443 CBS_len(&contents) != 0) {
444 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
445 return false;
446 }
447
448 if (!ssl_is_valid_ech_public_name(public_name)) {
449 // TODO(https://crbug.com/boringssl/275): The draft says ECHConfigs with
450 // invalid public names should be ignored, but LDH syntax failures are
451 // unambiguously invalid.
452 *out_supported = false;
453 return true;
454 }
455
456 out->public_key = public_key;
457 out->public_name = public_name;
458 // This function does not ensure |out->kem_id| and |out->cipher_suites| use
459 // supported algorithms. The caller must do this.
460 out->cipher_suites = cipher_suites;
461
462 bool has_unknown_mandatory_extension = false;
463 while (CBS_len(&extensions) != 0) {
464 uint16_t type;
465 CBS body;
466 if (!CBS_get_u16(&extensions, &type) ||
467 !CBS_get_u16_length_prefixed(&extensions, &body)) {
468 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
469 return false;
470 }
471 // We currently do not support any extensions.
472 if (type & 0x8000 || all_extensions_mandatory) {
473 // Extension numbers with the high bit set are mandatory. Continue parsing
474 // to enforce syntax, but we will ultimately ignore this ECHConfig as a
475 // client and reject it as a server.
476 has_unknown_mandatory_extension = true;
477 }
478 }
479
480 *out_supported = !has_unknown_mandatory_extension;
481 return true;
482 }
483
Init(Span<const uint8_t> ech_config,const EVP_HPKE_KEY * key,bool is_retry_config)484 bool ECHServerConfig::Init(Span<const uint8_t> ech_config,
485 const EVP_HPKE_KEY *key, bool is_retry_config) {
486 is_retry_config_ = is_retry_config;
487
488 // Parse the ECHConfig, rejecting all unsupported parameters and extensions.
489 // Unlike most server options, ECH's server configuration is serialized and
490 // configured in both the server and DNS. If the caller configures an
491 // unsupported parameter, this is a deployment error. To catch these errors,
492 // we fail early.
493 CBS cbs = ech_config;
494 bool supported;
495 if (!parse_ech_config(&cbs, &ech_config_, &supported,
496 /*all_extensions_mandatory=*/true)) {
497 return false;
498 }
499 if (CBS_len(&cbs) != 0) {
500 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
501 return false;
502 }
503 if (!supported) {
504 OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG);
505 return false;
506 }
507
508 CBS cipher_suites = ech_config_.cipher_suites;
509 while (CBS_len(&cipher_suites) > 0) {
510 uint16_t kdf_id, aead_id;
511 if (!CBS_get_u16(&cipher_suites, &kdf_id) ||
512 !CBS_get_u16(&cipher_suites, &aead_id)) {
513 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
514 return false;
515 }
516 // The server promises to support every option in the ECHConfig, so reject
517 // any unsupported cipher suites.
518 if (kdf_id != EVP_HPKE_HKDF_SHA256 || get_ech_aead(aead_id) == nullptr) {
519 OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG);
520 return false;
521 }
522 }
523
524 // Check the public key in the ECHConfig matches |key|.
525 uint8_t expected_public_key[EVP_HPKE_MAX_PUBLIC_KEY_LENGTH];
526 size_t expected_public_key_len;
527 if (!EVP_HPKE_KEY_public_key(key, expected_public_key,
528 &expected_public_key_len,
529 sizeof(expected_public_key))) {
530 return false;
531 }
532 if (ech_config_.kem_id != EVP_HPKE_KEM_id(EVP_HPKE_KEY_kem(key)) ||
533 MakeConstSpan(expected_public_key, expected_public_key_len) !=
534 ech_config_.public_key) {
535 OPENSSL_PUT_ERROR(SSL, SSL_R_ECH_SERVER_CONFIG_AND_PRIVATE_KEY_MISMATCH);
536 return false;
537 }
538
539 if (!EVP_HPKE_KEY_copy(key_.get(), key)) {
540 return false;
541 }
542
543 return true;
544 }
545
SetupContext(EVP_HPKE_CTX * ctx,uint16_t kdf_id,uint16_t aead_id,Span<const uint8_t> enc) const546 bool ECHServerConfig::SetupContext(EVP_HPKE_CTX *ctx, uint16_t kdf_id,
547 uint16_t aead_id,
548 Span<const uint8_t> enc) const {
549 // Check the cipher suite is supported by this ECHServerConfig.
550 CBS cbs(ech_config_.cipher_suites);
551 bool cipher_ok = false;
552 while (CBS_len(&cbs) != 0) {
553 uint16_t supported_kdf_id, supported_aead_id;
554 if (!CBS_get_u16(&cbs, &supported_kdf_id) ||
555 !CBS_get_u16(&cbs, &supported_aead_id)) {
556 return false;
557 }
558 if (kdf_id == supported_kdf_id && aead_id == supported_aead_id) {
559 cipher_ok = true;
560 break;
561 }
562 }
563 if (!cipher_ok) {
564 return false;
565 }
566
567 static const uint8_t kInfoLabel[] = "tls ech";
568 ScopedCBB info_cbb;
569 if (!CBB_init(info_cbb.get(), sizeof(kInfoLabel) + ech_config_.raw.size()) ||
570 !CBB_add_bytes(info_cbb.get(), kInfoLabel,
571 sizeof(kInfoLabel) /* includes trailing NUL */) ||
572 !CBB_add_bytes(info_cbb.get(), ech_config_.raw.data(),
573 ech_config_.raw.size())) {
574 return false;
575 }
576
577 assert(kdf_id == EVP_HPKE_HKDF_SHA256);
578 assert(get_ech_aead(aead_id) != NULL);
579 return EVP_HPKE_CTX_setup_recipient(
580 ctx, key_.get(), EVP_hpke_hkdf_sha256(), get_ech_aead(aead_id), enc.data(),
581 enc.size(), CBB_data(info_cbb.get()), CBB_len(info_cbb.get()));
582 }
583
ssl_is_valid_ech_config_list(Span<const uint8_t> ech_config_list)584 bool ssl_is_valid_ech_config_list(Span<const uint8_t> ech_config_list) {
585 CBS cbs = ech_config_list, child;
586 if (!CBS_get_u16_length_prefixed(&cbs, &child) || //
587 CBS_len(&child) == 0 || //
588 CBS_len(&cbs) > 0) {
589 return false;
590 }
591 while (CBS_len(&child) > 0) {
592 ECHConfig ech_config;
593 bool supported;
594 if (!parse_ech_config(&child, &ech_config, &supported,
595 /*all_extensions_mandatory=*/false)) {
596 return false;
597 }
598 }
599 return true;
600 }
601
select_ech_cipher_suite(const EVP_HPKE_KDF ** out_kdf,const EVP_HPKE_AEAD ** out_aead,Span<const uint8_t> cipher_suites,const bool has_aes_hardware)602 static bool select_ech_cipher_suite(const EVP_HPKE_KDF **out_kdf,
603 const EVP_HPKE_AEAD **out_aead,
604 Span<const uint8_t> cipher_suites,
605 const bool has_aes_hardware) {
606 const EVP_HPKE_AEAD *aead = nullptr;
607 CBS cbs = cipher_suites;
608 while (CBS_len(&cbs) != 0) {
609 uint16_t kdf_id, aead_id;
610 if (!CBS_get_u16(&cbs, &kdf_id) || //
611 !CBS_get_u16(&cbs, &aead_id)) {
612 return false;
613 }
614 // Pick the first common cipher suite, but prefer ChaCha20-Poly1305 if we
615 // don't have AES hardware.
616 const EVP_HPKE_AEAD *candidate = get_ech_aead(aead_id);
617 if (kdf_id != EVP_HPKE_HKDF_SHA256 || candidate == nullptr) {
618 continue;
619 }
620 if (aead == nullptr ||
621 (!has_aes_hardware && aead_id == EVP_HPKE_CHACHA20_POLY1305)) {
622 aead = candidate;
623 }
624 }
625 if (aead == nullptr) {
626 return false;
627 }
628
629 *out_kdf = EVP_hpke_hkdf_sha256();
630 *out_aead = aead;
631 return true;
632 }
633
ssl_select_ech_config(SSL_HANDSHAKE * hs,Span<uint8_t> out_enc,size_t * out_enc_len)634 bool ssl_select_ech_config(SSL_HANDSHAKE *hs, Span<uint8_t> out_enc,
635 size_t *out_enc_len) {
636 *out_enc_len = 0;
637 if (hs->max_version < TLS1_3_VERSION) {
638 // ECH requires TLS 1.3.
639 return true;
640 }
641
642 if (!hs->config->client_ech_config_list.empty()) {
643 CBS cbs = MakeConstSpan(hs->config->client_ech_config_list);
644 CBS child;
645 if (!CBS_get_u16_length_prefixed(&cbs, &child) || //
646 CBS_len(&child) == 0 || //
647 CBS_len(&cbs) > 0) {
648 return false;
649 }
650 // Look for the first ECHConfig with supported parameters.
651 while (CBS_len(&child) > 0) {
652 ECHConfig ech_config;
653 bool supported;
654 if (!parse_ech_config(&child, &ech_config, &supported,
655 /*all_extensions_mandatory=*/false)) {
656 return false;
657 }
658 const EVP_HPKE_KEM *kem = EVP_hpke_x25519_hkdf_sha256();
659 const EVP_HPKE_KDF *kdf;
660 const EVP_HPKE_AEAD *aead;
661 if (supported && //
662 ech_config.kem_id == EVP_HPKE_DHKEM_X25519_HKDF_SHA256 &&
663 select_ech_cipher_suite(&kdf, &aead, ech_config.cipher_suites,
664 hs->ssl->config->aes_hw_override
665 ? hs->ssl->config->aes_hw_override_value
666 : EVP_has_aes_hardware())) {
667 ScopedCBB info;
668 static const uint8_t kInfoLabel[] = "tls ech"; // includes trailing NUL
669 if (!CBB_init(info.get(), sizeof(kInfoLabel) + ech_config.raw.size()) ||
670 !CBB_add_bytes(info.get(), kInfoLabel, sizeof(kInfoLabel)) ||
671 !CBB_add_bytes(info.get(), ech_config.raw.data(),
672 ech_config.raw.size())) {
673 return false;
674 }
675
676 if (!EVP_HPKE_CTX_setup_sender(
677 hs->ech_hpke_ctx.get(), out_enc.data(), out_enc_len,
678 out_enc.size(), kem, kdf, aead, ech_config.public_key.data(),
679 ech_config.public_key.size(), CBB_data(info.get()),
680 CBB_len(info.get())) ||
681 !hs->inner_transcript.Init()) {
682 return false;
683 }
684
685 hs->selected_ech_config = MakeUnique<ECHConfig>(std::move(ech_config));
686 return hs->selected_ech_config != nullptr;
687 }
688 }
689 }
690
691 return true;
692 }
693
aead_overhead(const EVP_HPKE_AEAD * aead)694 static size_t aead_overhead(const EVP_HPKE_AEAD *aead) {
695 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
696 // TODO(https://crbug.com/boringssl/275): Having to adjust the overhead
697 // everywhere is tedious. Change fuzzer mode to append a fake tag but still
698 // otherwise be cleartext, refresh corpora, and then inline this function.
699 return 0;
700 #else
701 return EVP_AEAD_max_overhead(EVP_HPKE_AEAD_aead(aead));
702 #endif
703 }
704
705 // random_size returns a random value between |min| and |max|, inclusive.
random_size(size_t min,size_t max)706 static size_t random_size(size_t min, size_t max) {
707 assert(min < max);
708 size_t value;
709 RAND_bytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
710 return value % (max - min + 1) + min;
711 }
712
setup_ech_grease(SSL_HANDSHAKE * hs)713 static bool setup_ech_grease(SSL_HANDSHAKE *hs) {
714 assert(!hs->selected_ech_config);
715 if (hs->max_version < TLS1_3_VERSION || !hs->config->ech_grease_enabled) {
716 return true;
717 }
718
719 const uint16_t kdf_id = EVP_HPKE_HKDF_SHA256;
720 const bool has_aes_hw = hs->ssl->config->aes_hw_override
721 ? hs->ssl->config->aes_hw_override_value
722 : EVP_has_aes_hardware();
723 const EVP_HPKE_AEAD *aead =
724 has_aes_hw ? EVP_hpke_aes_128_gcm() : EVP_hpke_chacha20_poly1305();
725 static_assert(ssl_grease_ech_config_id < sizeof(hs->grease_seed),
726 "hs->grease_seed is too small");
727 uint8_t config_id = hs->grease_seed[ssl_grease_ech_config_id];
728
729 uint8_t enc[X25519_PUBLIC_VALUE_LEN];
730 uint8_t private_key_unused[X25519_PRIVATE_KEY_LEN];
731 X25519_keypair(enc, private_key_unused);
732
733 // To determine a plausible length for the payload, we estimate the size of a
734 // typical EncodedClientHelloInner without resumption:
735 //
736 // 2+32+1+2 version, random, legacy_session_id, legacy_compression_methods
737 // 2+4*2 cipher_suites (three TLS 1.3 ciphers, GREASE)
738 // 2 extensions prefix
739 // 5 inner encrypted_client_hello
740 // 4+1+2*2 supported_versions (TLS 1.3, GREASE)
741 // 4+1+10*2 outer_extensions (key_share, sigalgs, sct, alpn,
742 // supported_groups, status_request, psk_key_exchange_modes,
743 // compress_certificate, GREASE x2)
744 //
745 // The server_name extension has an overhead of 9 bytes. For now, arbitrarily
746 // estimate maximum_name_length to be between 32 and 100 bytes. Then round up
747 // to a multiple of 32, to match draft-ietf-tls-esni-13, section 6.1.3.
748 const size_t payload_len =
749 32 * random_size(128 / 32, 224 / 32) + aead_overhead(aead);
750 bssl::ScopedCBB cbb;
751 CBB enc_cbb, payload_cbb;
752 uint8_t *payload;
753 if (!CBB_init(cbb.get(), 256) ||
754 !CBB_add_u16(cbb.get(), kdf_id) ||
755 !CBB_add_u16(cbb.get(), EVP_HPKE_AEAD_id(aead)) ||
756 !CBB_add_u8(cbb.get(), config_id) ||
757 !CBB_add_u16_length_prefixed(cbb.get(), &enc_cbb) ||
758 !CBB_add_bytes(&enc_cbb, enc, sizeof(enc)) ||
759 !CBB_add_u16_length_prefixed(cbb.get(), &payload_cbb) ||
760 !CBB_add_space(&payload_cbb, &payload, payload_len) ||
761 !RAND_bytes(payload, payload_len) ||
762 !CBBFinishArray(cbb.get(), &hs->ech_client_outer)) {
763 return false;
764 }
765 return true;
766 }
767
ssl_encrypt_client_hello(SSL_HANDSHAKE * hs,Span<const uint8_t> enc)768 bool ssl_encrypt_client_hello(SSL_HANDSHAKE *hs, Span<const uint8_t> enc) {
769 SSL *const ssl = hs->ssl;
770 if (!hs->selected_ech_config) {
771 return setup_ech_grease(hs);
772 }
773
774 // Construct ClientHelloInner and EncodedClientHelloInner. See
775 // draft-ietf-tls-esni-13, sections 5.1 and 6.1.
776 ScopedCBB cbb, encoded_cbb;
777 CBB body;
778 bool needs_psk_binder;
779 Array<uint8_t> hello_inner;
780 if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO) ||
781 !CBB_init(encoded_cbb.get(), 256) ||
782 !ssl_write_client_hello_without_extensions(hs, &body,
783 ssl_client_hello_inner,
784 /*empty_session_id=*/false) ||
785 !ssl_write_client_hello_without_extensions(hs, encoded_cbb.get(),
786 ssl_client_hello_inner,
787 /*empty_session_id=*/true) ||
788 !ssl_add_clienthello_tlsext(hs, &body, encoded_cbb.get(),
789 &needs_psk_binder, ssl_client_hello_inner,
790 CBB_len(&body)) ||
791 !ssl->method->finish_message(ssl, cbb.get(), &hello_inner)) {
792 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
793 return false;
794 }
795
796 if (needs_psk_binder) {
797 size_t binder_len;
798 if (!tls13_write_psk_binder(hs, hs->inner_transcript, MakeSpan(hello_inner),
799 &binder_len)) {
800 return false;
801 }
802 // Also update the EncodedClientHelloInner.
803 auto encoded_binder =
804 MakeSpan(const_cast<uint8_t *>(CBB_data(encoded_cbb.get())),
805 CBB_len(encoded_cbb.get()))
806 .last(binder_len);
807 auto hello_inner_binder = MakeConstSpan(hello_inner).last(binder_len);
808 OPENSSL_memcpy(encoded_binder.data(), hello_inner_binder.data(),
809 binder_len);
810 }
811
812 ssl_do_msg_callback(ssl, /*is_write=*/1, SSL3_RT_CLIENT_HELLO_INNER,
813 hello_inner);
814 if (!hs->inner_transcript.Update(hello_inner)) {
815 return false;
816 }
817
818 // Pad the EncodedClientHelloInner. See draft-ietf-tls-esni-13, section 6.1.3.
819 size_t padding_len = 0;
820 size_t maximum_name_length = hs->selected_ech_config->maximum_name_length;
821 if (ssl->hostname) {
822 size_t hostname_len = strlen(ssl->hostname.get());
823 if (hostname_len <= maximum_name_length) {
824 padding_len = maximum_name_length - hostname_len;
825 }
826 } else {
827 // No SNI. Pad up to |maximum_name_length|, including server_name extension
828 // overhead.
829 padding_len = 9 + maximum_name_length;
830 }
831 // Pad the whole thing to a multiple of 32 bytes.
832 padding_len += 31 - ((CBB_len(encoded_cbb.get()) + padding_len - 1) % 32);
833 Array<uint8_t> encoded;
834 if (!CBB_add_zeros(encoded_cbb.get(), padding_len) ||
835 !CBBFinishArray(encoded_cbb.get(), &encoded)) {
836 return false;
837 }
838
839 // Encrypt |encoded|. See draft-ietf-tls-esni-13, section 6.1.1. First,
840 // assemble the extension with a placeholder value for ClientHelloOuterAAD.
841 // See draft-ietf-tls-esni-13, section 5.2.
842 const EVP_HPKE_KDF *kdf = EVP_HPKE_CTX_kdf(hs->ech_hpke_ctx.get());
843 const EVP_HPKE_AEAD *aead = EVP_HPKE_CTX_aead(hs->ech_hpke_ctx.get());
844 size_t payload_len = encoded.size() + aead_overhead(aead);
845 CBB enc_cbb, payload_cbb;
846 if (!CBB_init(cbb.get(), 256) ||
847 !CBB_add_u16(cbb.get(), EVP_HPKE_KDF_id(kdf)) ||
848 !CBB_add_u16(cbb.get(), EVP_HPKE_AEAD_id(aead)) ||
849 !CBB_add_u8(cbb.get(), hs->selected_ech_config->config_id) ||
850 !CBB_add_u16_length_prefixed(cbb.get(), &enc_cbb) ||
851 !CBB_add_bytes(&enc_cbb, enc.data(), enc.size()) ||
852 !CBB_add_u16_length_prefixed(cbb.get(), &payload_cbb) ||
853 !CBB_add_zeros(&payload_cbb, payload_len) ||
854 !CBBFinishArray(cbb.get(), &hs->ech_client_outer)) {
855 return false;
856 }
857
858 // Construct ClientHelloOuterAAD.
859 // TODO(https://crbug.com/boringssl/275): This ends up constructing the
860 // ClientHelloOuter twice. Instead, reuse |aad| for the ClientHello, now that
861 // draft-12 made the length prefixes match.
862 bssl::ScopedCBB aad;
863 if (!CBB_init(aad.get(), 256) ||
864 !ssl_write_client_hello_without_extensions(hs, aad.get(),
865 ssl_client_hello_outer,
866 /*empty_session_id=*/false) ||
867 !ssl_add_clienthello_tlsext(hs, aad.get(), /*out_encoded=*/nullptr,
868 &needs_psk_binder, ssl_client_hello_outer,
869 CBB_len(aad.get()))) {
870 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
871 return false;
872 }
873
874 // ClientHelloOuter may not require a PSK binder. Otherwise, we have a
875 // circular dependency.
876 assert(!needs_psk_binder);
877
878 // Replace the payload in |hs->ech_client_outer| with the encrypted value.
879 auto payload_span = MakeSpan(hs->ech_client_outer).last(payload_len);
880 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
881 // In fuzzer mode, the server expects a cleartext payload.
882 assert(payload_span.size() == encoded.size());
883 OPENSSL_memcpy(payload_span.data(), encoded.data(), encoded.size());
884 #else
885 if (!EVP_HPKE_CTX_seal(hs->ech_hpke_ctx.get(), payload_span.data(),
886 &payload_len, payload_span.size(), encoded.data(),
887 encoded.size(), CBB_data(aad.get()),
888 CBB_len(aad.get())) ||
889 payload_len != payload_span.size()) {
890 return false;
891 }
892 #endif // BORINGSSL_UNSAFE_FUZZER_MODE
893
894 return true;
895 }
896
897 BSSL_NAMESPACE_END
898
899 using namespace bssl;
900
SSL_set_enable_ech_grease(SSL * ssl,int enable)901 void SSL_set_enable_ech_grease(SSL *ssl, int enable) {
902 if (!ssl->config) {
903 return;
904 }
905 ssl->config->ech_grease_enabled = !!enable;
906 }
907
SSL_set1_ech_config_list(SSL * ssl,const uint8_t * ech_config_list,size_t ech_config_list_len)908 int SSL_set1_ech_config_list(SSL *ssl, const uint8_t *ech_config_list,
909 size_t ech_config_list_len) {
910 if (!ssl->config) {
911 return 0;
912 }
913
914 auto span = MakeConstSpan(ech_config_list, ech_config_list_len);
915 if (!ssl_is_valid_ech_config_list(span)) {
916 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ECH_CONFIG_LIST);
917 return 0;
918 }
919 return ssl->config->client_ech_config_list.CopyFrom(span);
920 }
921
SSL_get0_ech_name_override(const SSL * ssl,const char ** out_name,size_t * out_name_len)922 void SSL_get0_ech_name_override(const SSL *ssl, const char **out_name,
923 size_t *out_name_len) {
924 // When ECH is rejected, we use the public name. Note that, if
925 // |SSL_CTX_set_reverify_on_resume| is enabled, we reverify the certificate
926 // before the 0-RTT point. If also offering ECH, we verify as if
927 // ClientHelloInner was accepted and do not override. This works because, at
928 // this point, |ech_status| will be |ssl_ech_none|. See the
929 // ECH-Client-Reject-EarlyDataReject-OverrideNameOnRetry tests in runner.go.
930 const SSL_HANDSHAKE *hs = ssl->s3->hs.get();
931 if (!ssl->server && hs && ssl->s3->ech_status == ssl_ech_rejected) {
932 *out_name = reinterpret_cast<const char *>(
933 hs->selected_ech_config->public_name.data());
934 *out_name_len = hs->selected_ech_config->public_name.size();
935 } else {
936 *out_name = nullptr;
937 *out_name_len = 0;
938 }
939 }
940
SSL_get0_ech_retry_configs(const SSL * ssl,const uint8_t ** out_retry_configs,size_t * out_retry_configs_len)941 void SSL_get0_ech_retry_configs(
942 const SSL *ssl, const uint8_t **out_retry_configs,
943 size_t *out_retry_configs_len) {
944 const SSL_HANDSHAKE *hs = ssl->s3->hs.get();
945 if (!hs || !hs->ech_authenticated_reject) {
946 // It is an error to call this function except in response to
947 // |SSL_R_ECH_REJECTED|. Returning an empty string risks the caller
948 // mistakenly believing the server has disabled ECH. Instead, return a
949 // non-empty ECHConfigList with a syntax error, so the subsequent
950 // |SSL_set1_ech_config_list| call will fail.
951 assert(0);
952 static const uint8_t kPlaceholder[] = {
953 kECHConfigVersion >> 8, kECHConfigVersion & 0xff, 0xff, 0xff, 0xff};
954 *out_retry_configs = kPlaceholder;
955 *out_retry_configs_len = sizeof(kPlaceholder);
956 return;
957 }
958
959 *out_retry_configs = hs->ech_retry_configs.data();
960 *out_retry_configs_len = hs->ech_retry_configs.size();
961 }
962
SSL_marshal_ech_config(uint8_t ** out,size_t * out_len,uint8_t config_id,const EVP_HPKE_KEY * key,const char * public_name,size_t max_name_len)963 int SSL_marshal_ech_config(uint8_t **out, size_t *out_len, uint8_t config_id,
964 const EVP_HPKE_KEY *key, const char *public_name,
965 size_t max_name_len) {
966 Span<const uint8_t> public_name_u8 = MakeConstSpan(
967 reinterpret_cast<const uint8_t *>(public_name), strlen(public_name));
968 if (!ssl_is_valid_ech_public_name(public_name_u8)) {
969 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ECH_PUBLIC_NAME);
970 return 0;
971 }
972
973 // The maximum name length is encoded in one byte.
974 if (max_name_len > 0xff) {
975 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
976 return 0;
977 }
978
979 // See draft-ietf-tls-esni-13, section 4.
980 ScopedCBB cbb;
981 CBB contents, child;
982 uint8_t *public_key;
983 size_t public_key_len;
984 if (!CBB_init(cbb.get(), 128) || //
985 !CBB_add_u16(cbb.get(), kECHConfigVersion) ||
986 !CBB_add_u16_length_prefixed(cbb.get(), &contents) ||
987 !CBB_add_u8(&contents, config_id) ||
988 !CBB_add_u16(&contents, EVP_HPKE_KEM_id(EVP_HPKE_KEY_kem(key))) ||
989 !CBB_add_u16_length_prefixed(&contents, &child) ||
990 !CBB_reserve(&child, &public_key, EVP_HPKE_MAX_PUBLIC_KEY_LENGTH) ||
991 !EVP_HPKE_KEY_public_key(key, public_key, &public_key_len,
992 EVP_HPKE_MAX_PUBLIC_KEY_LENGTH) ||
993 !CBB_did_write(&child, public_key_len) ||
994 !CBB_add_u16_length_prefixed(&contents, &child) ||
995 // Write a default cipher suite configuration.
996 !CBB_add_u16(&child, EVP_HPKE_HKDF_SHA256) ||
997 !CBB_add_u16(&child, EVP_HPKE_AES_128_GCM) ||
998 !CBB_add_u16(&child, EVP_HPKE_HKDF_SHA256) ||
999 !CBB_add_u16(&child, EVP_HPKE_CHACHA20_POLY1305) ||
1000 !CBB_add_u8(&contents, max_name_len) ||
1001 !CBB_add_u8_length_prefixed(&contents, &child) ||
1002 !CBB_add_bytes(&child, public_name_u8.data(), public_name_u8.size()) ||
1003 // TODO(https://crbug.com/boringssl/275): Reserve some GREASE extensions
1004 // and include some.
1005 !CBB_add_u16(&contents, 0 /* no extensions */) ||
1006 !CBB_finish(cbb.get(), out, out_len)) {
1007 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
1008 return 0;
1009 }
1010 return 1;
1011 }
1012
SSL_ECH_KEYS_new()1013 SSL_ECH_KEYS *SSL_ECH_KEYS_new() { return New<SSL_ECH_KEYS>(); }
1014
SSL_ECH_KEYS_up_ref(SSL_ECH_KEYS * keys)1015 void SSL_ECH_KEYS_up_ref(SSL_ECH_KEYS *keys) { keys->UpRefInternal(); }
1016
SSL_ECH_KEYS_free(SSL_ECH_KEYS * keys)1017 void SSL_ECH_KEYS_free(SSL_ECH_KEYS *keys) {
1018 if (keys != nullptr) {
1019 keys->DecRefInternal();
1020 }
1021 }
1022
SSL_ECH_KEYS_add(SSL_ECH_KEYS * configs,int is_retry_config,const uint8_t * ech_config,size_t ech_config_len,const EVP_HPKE_KEY * key)1023 int SSL_ECH_KEYS_add(SSL_ECH_KEYS *configs, int is_retry_config,
1024 const uint8_t *ech_config, size_t ech_config_len,
1025 const EVP_HPKE_KEY *key) {
1026 UniquePtr<ECHServerConfig> parsed_config = MakeUnique<ECHServerConfig>();
1027 if (!parsed_config) {
1028 return 0;
1029 }
1030 if (!parsed_config->Init(MakeConstSpan(ech_config, ech_config_len), key,
1031 !!is_retry_config)) {
1032 OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
1033 return 0;
1034 }
1035 if (!configs->configs.Push(std::move(parsed_config))) {
1036 return 0;
1037 }
1038 return 1;
1039 }
1040
SSL_ECH_KEYS_has_duplicate_config_id(const SSL_ECH_KEYS * keys)1041 int SSL_ECH_KEYS_has_duplicate_config_id(const SSL_ECH_KEYS *keys) {
1042 bool seen[256] = {false};
1043 for (const auto &config : keys->configs) {
1044 if (seen[config->ech_config().config_id]) {
1045 return 1;
1046 }
1047 seen[config->ech_config().config_id] = true;
1048 }
1049 return 0;
1050 }
1051
SSL_ECH_KEYS_marshal_retry_configs(const SSL_ECH_KEYS * keys,uint8_t ** out,size_t * out_len)1052 int SSL_ECH_KEYS_marshal_retry_configs(const SSL_ECH_KEYS *keys, uint8_t **out,
1053 size_t *out_len) {
1054 ScopedCBB cbb;
1055 CBB child;
1056 if (!CBB_init(cbb.get(), 128) ||
1057 !CBB_add_u16_length_prefixed(cbb.get(), &child)) {
1058 return false;
1059 }
1060 for (const auto &config : keys->configs) {
1061 if (config->is_retry_config() &&
1062 !CBB_add_bytes(&child, config->ech_config().raw.data(),
1063 config->ech_config().raw.size())) {
1064 return false;
1065 }
1066 }
1067 return CBB_finish(cbb.get(), out, out_len);
1068 }
1069
SSL_CTX_set1_ech_keys(SSL_CTX * ctx,SSL_ECH_KEYS * keys)1070 int SSL_CTX_set1_ech_keys(SSL_CTX *ctx, SSL_ECH_KEYS *keys) {
1071 bool has_retry_config = false;
1072 for (const auto &config : keys->configs) {
1073 if (config->is_retry_config()) {
1074 has_retry_config = true;
1075 break;
1076 }
1077 }
1078 if (!has_retry_config) {
1079 OPENSSL_PUT_ERROR(SSL, SSL_R_ECH_SERVER_WOULD_HAVE_NO_RETRY_CONFIGS);
1080 return 0;
1081 }
1082 UniquePtr<SSL_ECH_KEYS> owned_keys = UpRef(keys);
1083 MutexWriteLock lock(&ctx->lock);
1084 ctx->ech_keys.swap(owned_keys);
1085 return 1;
1086 }
1087
SSL_ech_accepted(const SSL * ssl)1088 int SSL_ech_accepted(const SSL *ssl) {
1089 if (SSL_in_early_data(ssl) && !ssl->server) {
1090 // In the client early data state, we report properties as if the server
1091 // accepted early data. The server can only accept early data with
1092 // ClientHelloInner.
1093 return ssl->s3->hs->selected_ech_config != nullptr;
1094 }
1095
1096 return ssl->s3->ech_status == ssl_ech_accepted;
1097 }
1098