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