Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encrypted Client Hello support (client only) #1718

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

cpu
Copy link
Member

@cpu cpu commented Jan 2, 2024

Description

This branch brings encrypted client hello (ECH) compatibility to Rustls clients based on draft-ietf-tls-esni-18.

Closes #199

Limitations

Comparison to previous PRs:

Server Name Enum

Initially we expected to update the ServerName enum to have a variant for ECH - I tried this initially and found that it didn't fit the design of ECH very well. Mainly the issue is that we need to carry a lot of additional state beyond the inner SNI name. Putting that state into the ServerName is challenging, and an impedance mismatch with the existing usage. Having separate state and the ECH variant in ServerName meant having two pieces of information and having to contend with what to do if one is present but not the other. This is also made increasingly complex since we lifted the ServerName type into the pki-types crate. As a point of reference, you can compare this branch with the approach in #663 where a ServerIdentity enum stands in for ServerName and contains a EncryptedClientHello(Box<EncryptedClientHello>) variant that holds a Box of heap allocated state.

Credit where credit is due

I started this branch by first adopting work from what @sayrer started in #663. Many thanks for kicking this effort off and giving me a solid foundation to start with!

Some major changes compared to that branch:

  • This branch updates from draft-10 to draft-18, rolling in associated changes (mostly related to confirmation, extension types, etc).
  • As discussed above, I opted to not use a ServerName variant for holding the inner SNI name and associated state.
  • I've caught up the diff to the current Rustls main, adjusting for various Codec changes and associated code drift.
  • HPKE usage is handled through the trait, abstracting away the choice of implementation as opposed to using hpke-rs directly.
  • An HPKE provider backed by aws-lc-rs was implemented so we can have a crypto provider out-of-box that supports ECH.
  • I've implemented support for ECH confirmation across Hello Retry Requests - this in turn required reworking how the "inner" transcript is maintained, calculating the HRR confirmation, and threading through more bits of state across the handshake.
  • I've implemented support for session resumption in the inner hello when using ECH, including support for the GREASE PSK in the outer hello.
  • I've tried to avoid duplicating encoding code, instead introducing an encoding Purpose that lets us share the message encoding logic as much as possible with the exception of the parts that are unique for ECH confirmation.
  • I've tried to roll requirements into the existing code where possible to avoid duplication (e.g. updating the hash transcripts to allow forking, updating the key derivation code to allow confirmation calculation).
  • I've wired in the "ECH required" alert, and pulling out ECH retry configs from the server's encrypted extensions. The retry configs and alert are held until the end of the handshake per spec.
  • The ECH config HPKE suite is considered w.r.t FIPS status of the client config, or client connection, when using ECH.
  • I've implemented test coverage with boringssl's bogo test suite, fixing divergences as appropriate.
  • Probably some additional items I'm forgetting!

@cpu cpu self-assigned this Jan 2, 2024
Copy link

codecov bot commented Jan 2, 2024

Codecov Report

Attention: Patch coverage is 94.08961% with 62 lines in your changes missing coverage. Please review.

Project coverage is 94.08%. Comparing base (756b7dc) to head (13081b9).

Current head 13081b9 differs from pull request most recent head e96b01d

Please upload reports for the commit e96b01d to get more accurate results.

Files Patch % Lines
rustls/src/client/ech.rs 94.78% 24 Missing ⚠️
rustls/src/msgs/handshake.rs 90.58% 21 Missing ⚠️
provider-example/src/hpke.rs 0.00% 11 Missing ⚠️
rustls/src/error.rs 0.00% 5 Missing ⚠️
rustls/src/client/hs.rs 99.19% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1718      +/-   ##
==========================================
- Coverage   94.18%   94.08%   -0.10%     
==========================================
  Files          96       97       +1     
  Lines       20648    21516     +868     
==========================================
+ Hits        19447    20243     +796     
- Misses       1201     1273      +72     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@ctz
Copy link
Member

ctz commented Jan 2, 2024

As an intermediate step it might be worthwhile to add a Go/OpenSSL server tests in CI (input here welcome!).

Definitely worth looking at the boringssl test suite -- there are ECH tests there that should be ready to go (albeit with some neccessary additions to our bogo_shim.rs). Currently they are disabled here:

https://github.com/rustls/rustls/blob/main/bogo/config.json#L34

@cpu
Copy link
Member Author

cpu commented Jan 2, 2024

Definitely worth looking at the boringssl test suite -- there are ECH tests there that should be ready to go

Oh great! Thanks for the pointer. I will focus attention there 👍

@djc
Copy link
Member

djc commented Jan 4, 2024

Might also be useful to do a bogo update before this work? I assume ECH tests may have evolved since June.

Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! I have a bunch of nits (hope that's useful at this stage) but not much substantial feedback.

I feel like the commit history overindexes a bit on small commits and might benefit from some squashing of things together so more context is available in commits.

rustls/src/crypto/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/hpke.rs Outdated Show resolved Hide resolved
rustls/src/enums.rs Outdated Show resolved Hide resolved
rustls/src/enums.rs Outdated Show resolved Hide resolved
rustls/src/msgs/handshake.rs Outdated Show resolved Hide resolved
rustls/src/client/hs.rs Outdated Show resolved Hide resolved
rustls/src/client/hs.rs Show resolved Hide resolved
rustls/src/client/tls13.rs Outdated Show resolved Hide resolved
rustls/src/client/tls13.rs Outdated Show resolved Hide resolved
provider-example/examples/ech-client.rs Outdated Show resolved Hide resolved
@cpu
Copy link
Member Author

cpu commented Jan 9, 2024

Now that a bunch of the smaller work has been pulled out and merged I will try to find time to rebase this and address the remaining feedback from djc's first review pass.

As a quick note: ISRG wants me to focus on finishing some of the remaining no-alloc/async work ahead of prioritizing ECH completion, so I'll be picking up work for this branch after making more progress on that front.

@ctz
Copy link
Member

ctz commented Jan 10, 2024

Might also be useful to do a bogo update before this work? I assume ECH tests may have evolved since June.

#1740

@cpu
Copy link
Member Author

cpu commented Jan 18, 2024

I needed a break from my current tasks so I rebased this branch and addressed some of the low hanging review feedback. I haven't resolved all of it yet (so probably not ready for a second pass).

@sayrer
Copy link
Contributor

sayrer commented Mar 26, 2024

It all looks good to me.

I think the Server Name Enum choices are good. I just threw stuff on the heap because I didn't really know what was going to be required. You're right that the spec is complicated and out-of-order when you sit down to write the implementation. I'd recommend reading it all the way through once before writing any more code, just to keep it all in your head. That's what I had to do a few times, anyway.

The HPKE trait is good, too. I wrote mine when rustls only had ring and didn't let one vary the dependencies, and was assuming ring would add that. I see you already have the OpenSSL server in your tests. You can find some variations that will trigger HRR via your HPKE choice here:
https://mailarchive.ietf.org/arch/msg/tls/DmMuf-CCzNNxSNY9LvxxQlu-fy4/

Those might be good for connect tests, and as a way to go once the server code is added.

As a practical matter, I think you will have to implement the handshake compression stuff. I showed up because I saw that you've added support for Kyber/X25519. In that case, you will really need it.

@cpu
Copy link
Member Author

cpu commented Mar 26, 2024

Hey sayrer,

It all looks good to me.

Awesome. Thanks so much for taking a look. I'm focused on this branch again as of the past couple of days and hope we can get it across the line soon.

I think the Server Name Enum choices are good. I just threw stuff on the heap because I didn't really know what was going to be required.

Makes sense 👍

You're right that the spec is complicated and out-of-order when you sit down to write the implementation. I'd recommend reading it all the way through once before writing any more code, just to keep it all in your head. That's what I had to do a few times, anyway.

Yeah :-( That's what I ended up doing too. It's some comfort to hear I wasn't alone in feeling this. From my perspective it feels like it's a bit too late in the document's process to try and fix the "editorial narrative" to be closer aligned to what an implementer might want. That's unfortunate but c'est la vie.

You can find some variations that will trigger HRR via your HPKE choice here:
https://mailarchive.ietf.org/arch/msg/tls/DmMuf-CCzNNxSNY9LvxxQlu-fy4/

Useful pointers, thank you 🔖

As a practical matter, I think you will have to implement the handshake compression stuff. I showed up because I saw that you've added support for Kyber/X25519. In that case, you will really need it.

100% agreed. IIRC your initial branch had an implementation of the compression (or at least the start of one). I think we'll want to revive that before merging this work. I left it out only to try and keep the scope contained while figuring out the bigger picture.

Thanks again for the feedback (and the original work!).

@sayrer
Copy link
Contributor

sayrer commented Mar 26, 2024

100% agreed. IIRC your initial branch had an implementation of the compression (or at least the start of one). I think we'll want to revive that before merging this work. I left it out only to try and keep the scope contained while figuring out the bigger picture.

I think it was a little more ready for that part than this branch, but it didn't do it either (I think it did sort the extensions to prepare, I think the draft-07 one was better). It's been a while, but it really wanted some Iter features that were nightly-only at the time. I think you can probably get a good version now.

@sayrer
Copy link
Contributor

sayrer commented Mar 28, 2024

For that reason we may want to keep this as an experimental feature, and potentially hold merging the work?

I don't think you need to be so cautious. Firefox, Chrome, and Cloudflare are all shipping it.

Screenshot 2024-03-28 at 9 48 49 AM

@dconnolly
Copy link

For that reason we may want to keep this as an experimental feature, and potentially hold merging the work?

I don't think you need to be so cautious. Firefox, Chrome, and Cloudflare are all shipping it.

ECH has gone through working group last call so it's unlikely to change significantly beyond version -18

@cpu
Copy link
Member Author

cpu commented Apr 12, 2024

cpu force-pushed the cpu-client-ech branch from 9e8d367 to 68cfb74

Pushed some progress from my local branch:

  • changed the user facing API for configuring ECH to fit into the builder paradigm.
  • git patch on add EchConfigListBytes for encrypted client hello configs pki-types#46 to experiment with a typed representation for the TLS encoded ECH config bytes. (Note; this also temporarily breaks the cargo semver and fuzzer targets/clippy since they won't play nice with the git patch).
  • adjusted to be no-std compatible throughout, removing a pile of #[cfg(feature = "std")] gates I threw all over to get the build passing before.
  • updated the ECH config handling to properly detect unsupported but mandatory ECH config extensions.
  • reworked the GREASE implementation to provide more control to the user, and to fit better into the new builder model.
  • reworked the commit history to prefer a style where pieces are introduced when they're used instead of ahead of time with dead_code allows.
  • the ech-client example program is more sophisticated and easier to use for testing.
  • some other small bits of tidying/refactoring.

I'm still working through bogo coverage and that's now my major focus. I've grokked the overall test approach and done some bogo_shim updates and initial results indicate there's a ways to go w.r.t protocol compatibility in the cornercases. In particular the client ECH bogo tests are flagging that the inner hello contains some extensions it shouldn't, and most importantly, that I believe I've broken resumption in the presence of ECH. Hope to have some more updates on this front shortly.

rustls/src/client/ech.rs Outdated Show resolved Hide resolved
@cpu cpu force-pushed the cpu-client-ech branch 2 times, most recently from 4bba847 to 4feb74f Compare June 3, 2024 21:29
Cargo.toml Outdated Show resolved Hide resolved
Copy link

rustls-benchmarking bot commented Jun 4, 2024

Benchmark results

Instruction counts

Significant differences

⚠️ There are significant instruction count differences

Click to expand
Scenario Baseline Candidate Diff Threshold
handshake_session_id_aws_lc_rs_1.2_rsa_aes_client 3970626 3993188 ⚠️ 22562 (0.57%) 0.20%
handshake_tickets_aws_lc_rs_1.2_rsa_aes_client 4297820 4321451 ⚠️ 23631 (0.55%) 0.20%
handshake_session_id_ring_1.2_rsa_aes_client 4236512 4258123 ⚠️ 21611 (0.51%) 0.20%
handshake_tickets_ring_1.2_rsa_aes_client 4507183 4529185 ⚠️ 22002 (0.49%) 0.20%
handshake_tickets_ring_1.2_rsa_aes_server 4667501 4680991 ⚠️ 13490 (0.29%) 0.20%
handshake_session_id_ring_1.2_rsa_aes_server 4235720 4247706 ⚠️ 11986 (0.28%) 0.20%

Other differences

Click to expand
Scenario Baseline Candidate Diff Threshold
handshake_session_id_aws_lc_rs_1.2_rsa_aes_server 3925961 3961181 35220 (0.90%) 6.70%
handshake_tickets_aws_lc_rs_1.2_rsa_aes_server 4418142 4437584 19442 (0.44%) 3.26%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_aes_client 8727101 8697636 -29465 (-0.34%) 0.83%
handshake_no_resume_aws_lc_rs_1.2_rsa_aes_server 13399457 13361275 -38182 (-0.28%) 1.12%
transfer_no_resume_aws_lc_rs_1.2_rsa_aes_server 46344207 46459077 114870 (0.25%) 0.44%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_aes_client 30775718 30848740 73022 (0.24%) 0.45%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_aes_client 30594548 30665453 70905 (0.23%) 0.37%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_chacha_client 30536754 30597235 60481 (0.20%) 0.36%
handshake_session_id_aws_lc_rs_1.3_rsa_aes_server 32868892 32922115 53223 (0.16%) 0.38%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_chacha_client 30771427 30811924 40497 (0.13%) 0.42%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_chacha_client 30581091 30619131 38040 (0.12%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_aes_client 58211353 58280884 69531 (0.12%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_chacha_client 30783610 30819749 36139 (0.12%) 0.20%
handshake_session_id_aws_lc_rs_1.3_rsa_chacha_client 30595883 30629801 33918 (0.11%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_chacha_client 30801733 30835587 33854 (0.11%) 0.20%
handshake_session_id_aws_lc_rs_1.3_rsa_aes_client 30622341 30655912 33571 (0.11%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_aes_client 30609750 30642789 33039 (0.11%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_aes_client 30826529 30859147 32618 (0.11%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_chacha_server 33144164 33178414 34250 (0.10%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_aes_server 33169213 33203194 33981 (0.10%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_aes_client 30808520 30839693 31173 (0.10%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_chacha_server 33144225 33177623 33398 (0.10%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_aes_server 33169639 33202397 32758 (0.10%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_aes_server 33163381 33194089 30708 (0.09%) 0.73%
handshake_tickets_ring_1.3_ecdsap256_chacha_server 43623492 43661166 37674 (0.09%) 0.20%
handshake_tickets_ring_1.3_ecdsap256_chacha_client 41972194 42006628 34434 (0.08%) 0.20%
handshake_session_id_ring_1.3_rsa_aes_client 41865229 41899371 34142 (0.08%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_aes_client 41847166 41881105 33939 (0.08%) 0.20%
handshake_tickets_ring_1.3_rsa_chacha_client 41985784 42019465 33681 (0.08%) 0.20%
handshake_tickets_ring_1.3_rsa_aes_client 42054150 42087847 33697 (0.08%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_client 8740580 8733617 -6963 (-0.08%) 1.10%
handshake_session_id_ring_1.3_ecdsap384_chacha_client 41767065 41800040 32975 (0.08%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_aes_client 41852573 41885488 32915 (0.08%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_chacha_client 41966854 41999522 32668 (0.08%) 0.20%
handshake_session_id_ring_1.3_rsa_chacha_client 41784902 41817317 32415 (0.08%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_aes_client 42036234 42068777 32543 (0.08%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_chacha_server 13788831 13799159 10328 (0.07%) 0.77%
handshake_tickets_ring_1.3_ecdsap384_chacha_server 43624078 43656693 32615 (0.07%) 0.20%
handshake_tickets_ring_1.3_rsa_chacha_server 43621819 43654387 32568 (0.07%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_chacha_client 41772600 41802963 30363 (0.07%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_aes_server 43698704 43729423 30719 (0.07%) 0.20%
handshake_tickets_ring_1.3_rsa_aes_server 43696300 43727009 30709 (0.07%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_chacha_server 32877228 32899156 21928 (0.07%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_aes_server 32918600 32940261 21661 (0.07%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_chacha_server 32877879 32899425 21546 (0.07%) 0.20%
handshake_session_id_aws_lc_rs_1.3_rsa_chacha_server 32869070 32847629 -21441 (-0.07%) 0.58%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_aes_server 32918546 32939516 20970 (0.06%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_rsa_aes_client 58234958 58271944 36986 (0.06%) 0.20%
handshake_tickets_ring_1.3_ecdsap256_aes_client 42044983 42071473 26490 (0.06%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_aes_client 58314187 58350755 36568 (0.06%) 0.20%
transfer_no_resume_ring_1.3_rsa_aes_client 58318270 58354294 36024 (0.06%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_aes_client 58315020 58350937 35917 (0.06%) 0.20%
handshake_no_resume_ring_1.3_ecdsap256_aes_server 2129851 2131118 1267 (0.06%) 0.83%
handshake_no_resume_ring_1.3_rsa_chacha_server 12175817 12183007 7190 (0.06%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_aes_server 13801514 13793414 -8100 (-0.06%) 1.10%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_aes_client 58232646 58266447 33801 (0.06%) 0.20%
handshake_tickets_ring_1.3_ecdsap256_aes_server 43703905 43729113 25208 (0.06%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_aes_client 2225334 2226571 1237 (0.06%) 0.20%
handshake_no_resume_ring_1.2_rsa_aes_server 11981940 11988501 6561 (0.05%) 0.20%
handshake_no_resume_ring_1.3_rsa_aes_server 12170382 12176871 6489 (0.05%) 0.20%
transfer_no_resume_ring_1.2_rsa_aes_client 58198109 58228046 29937 (0.05%) 0.20%
handshake_no_resume_aws_lc_rs_1.2_rsa_aes_client 2015261 2016297 1036 (0.05%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_chacha_client 2232419 2233550 1131 (0.05%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_client 92682580 92729220 46640 (0.05%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_chacha_server 43327560 43349208 21648 (0.05%) 0.20%
handshake_session_id_ring_1.3_rsa_chacha_server 43324685 43345982 21297 (0.05%) 0.20%
handshake_no_resume_ring_1.3_ecdsap256_chacha_server 2132020 2133054 1034 (0.05%) 0.75%
handshake_no_resume_ring_1.3_rsa_aes_client 2949296 2950712 1416 (0.05%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_server 1913830 1914743 913 (0.05%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_aes_server 1910759 1911669 910 (0.05%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_chacha_server 43327741 43348072 20331 (0.05%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_aes_client 3380238 3381794 1556 (0.05%) 0.23%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_client 92686120 92728241 42121 (0.05%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_aes_server 43428241 43447531 19290 (0.04%) 0.20%
transfer_no_resume_aws_lc_rs_1.2_rsa_aes_client 68656734 68686420 29686 (0.04%) 0.20%
handshake_session_id_ring_1.3_rsa_aes_server 43425170 43443717 18547 (0.04%) 0.20%
handshake_no_resume_ring_1.3_rsa_chacha_client 2955318 2956579 1261 (0.04%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_chacha_server 33151033 33164259 13226 (0.04%) 0.57%
handshake_no_resume_ring_1.3_ecdsap256_chacha_client 3916513 3918066 1553 (0.04%) 0.41%
transfer_no_resume_ring_1.3_ecdsap384_chacha_client 92646395 92682750 36355 (0.04%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_rsa_chacha_client 92693007 92729364 36357 (0.04%) 0.20%
transfer_no_resume_ring_1.3_rsa_chacha_client 92651004 92687225 36221 (0.04%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_chacha_client 92649799 92685581 35782 (0.04%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_aes_server 43429423 43446184 16761 (0.04%) 0.20%
handshake_no_resume_ring_1.2_rsa_aes_client 2852483 2853519 1036 (0.04%) 0.20%
handshake_no_resume_ring_1.3_ecdsap256_aes_client 3915012 3916327 1315 (0.03%) 0.46%
transfer_no_resume_aws_lc_rs_1.3_rsa_aes_server 46386535 46398754 12219 (0.03%) 0.44%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_aes_server 4287360 4288351 991 (0.02%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_server 4290909 4291782 873 (0.02%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_rsa_chacha_server 80603756 80589532 -14224 (-0.02%) 0.20%
transfer_no_resume_ring_1.2_rsa_aes_server 46353025 46357024 3999 (0.01%) 0.20%
transfer_no_resume_ring_1.3_rsa_aes_server 46447400 46451274 3874 (0.01%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_chacha_server 13740323 13741149 826 (0.01%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_client 3382742 3382543 -199 (-0.01%) 0.27%
transfer_no_resume_ring_1.3_rsa_chacha_server 80516501 80519795 3294 (0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_aes_client 35472016 35473218 1202 (0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_aes_server 13738591 13739000 409 (0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_chacha_client 35474253 35475247 994 (0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_aes_server 46433709 46432559 -1150 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_aes_server 46440073 46438929 -1144 (-0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_server 80612841 80611808 -1033 (-0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_aes_server 46432386 46431876 -510 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_chacha_server 80512117 80511277 -840 (-0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_server 80611654 80611057 -597 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_chacha_server 80508456 80507930 -526 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_aes_server 46442951 46443126 175 (0.00%) 0.20%

Wall-time

Significant differences

⚠️ There are significant wall-time differences

Click to expand
Scenario Baseline Candidate Diff Threshold
handshake_no_resume_ring_1.3_rsa_chacha 1.00 ms 0.99 ms ✅ -0.02 ms (-1.71%) 1.00%
handshake_no_resume_ring_1.3_rsa_aes 1.00 ms 0.99 ms ✅ -0.02 ms (-1.68%) 1.00%

Other differences

Click to expand
Scenario Baseline Candidate Diff Threshold
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_aes 4.57 ms 4.47 ms -0.10 ms (-2.10%) 5.87%
transfer_no_resume_aws_lc_rs_1.2_rsa_aes 5.51 ms 5.40 ms -0.11 ms (-1.99%) 4.43%
transfer_no_resume_aws_lc_rs_1.3_rsa_aes 5.51 ms 5.40 ms -0.11 ms (-1.97%) 4.56%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_aes 5.29 ms 5.19 ms -0.10 ms (-1.83%) 4.88%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_aes 485.22 µs 477.30 µs -7.92 µs (-1.63%) 2.30%
transfer_no_resume_ring_1.2_rsa_aes 6.81 ms 6.70 ms -0.11 ms (-1.60%) 3.03%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_chacha 483.88 µs 476.47 µs -7.41 µs (-1.53%) 2.91%
transfer_no_resume_ring_1.3_rsa_aes 6.89 ms 6.78 ms -0.11 ms (-1.53%) 3.54%
transfer_no_resume_ring_1.3_ecdsap256_aes 6.39 ms 6.30 ms -0.09 ms (-1.46%) 3.69%
handshake_no_resume_ring_1.3_ecdsap256_chacha 508.16 µs 501.79 µs -6.37 µs (-1.25%) 2.34%
handshake_no_resume_ring_1.3_ecdsap256_aes 510.46 µs 504.09 µs -6.37 µs (-1.25%) 2.61%
transfer_no_resume_ring_1.3_ecdsap384_aes 9.48 ms 9.40 ms -0.08 ms (-0.89%) 2.72%
handshake_no_resume_aws_lc_rs_1.2_rsa_aes 1.36 ms 1.35 ms -0.01 ms (-0.89%) 3.28%
handshake_no_resume_aws_lc_rs_1.3_rsa_chacha 1.41 ms 1.39 ms -0.01 ms (-0.83%) 3.61%
transfer_no_resume_ring_1.3_ecdsap256_chacha 13.04 ms 12.94 ms -0.10 ms (-0.78%) 1.81%
transfer_no_resume_ring_1.3_rsa_chacha 13.54 ms 13.43 ms -0.11 ms (-0.78%) 1.83%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_aes 1.20 ms 1.19 ms -0.01 ms (-0.70%) 1.00%
handshake_no_resume_ring_1.2_rsa_aes 981.34 µs 974.87 µs -6.47 µs (-0.66%) 1.00%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_chacha 1.19 ms 1.18 ms -0.01 ms (-0.65%) 1.33%
transfer_no_resume_ring_1.3_ecdsap384_chacha 16.13 ms 16.04 ms -0.09 ms (-0.58%) 1.52%
transfer_no_resume_aws_lc_rs_1.3_rsa_chacha 13.98 ms 13.90 ms -0.08 ms (-0.58%) 1.82%
handshake_no_resume_aws_lc_rs_1.3_rsa_aes 1.41 ms 1.41 ms -0.01 ms (-0.53%) 4.02%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_chacha 13.04 ms 12.97 ms -0.07 ms (-0.53%) 2.24%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_chacha 13.74 ms 13.68 ms -0.07 ms (-0.51%) 1.91%
handshake_session_id_aws_lc_rs_1.2_rsa_aes 2.05 ms 2.04 ms -0.01 ms (-0.44%) 3.44%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_chacha 6.04 ms 6.02 ms -0.02 ms (-0.36%) 1.76%
handshake_session_id_aws_lc_rs_1.3_rsa_aes 6.30 ms 6.27 ms -0.02 ms (-0.36%) 2.04%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_aes 5.35 ms 5.33 ms -0.02 ms (-0.36%) 2.43%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_aes 6.07 ms 6.05 ms -0.02 ms (-0.35%) 2.14%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_chacha 5.34 ms 5.32 ms -0.02 ms (-0.33%) 1.71%
handshake_session_id_aws_lc_rs_1.3_rsa_chacha 6.28 ms 6.26 ms -0.02 ms (-0.32%) 1.87%
handshake_tickets_aws_lc_rs_1.2_rsa_aes 2.21 ms 2.20 ms -0.01 ms (-0.26%) 2.56%
handshake_session_id_ring_1.2_rsa_aes 1.56 ms 1.55 ms -0.00 ms (-0.26%) 1.00%
handshake_session_id_ring_1.3_rsa_chacha 7.20 ms 7.18 ms -0.02 ms (-0.21%) 1.00%
handshake_session_id_ring_1.3_rsa_aes 7.25 ms 7.23 ms -0.01 ms (-0.20%) 1.00%
handshake_no_resume_ring_1.3_ecdsap384_chacha 3.60 ms 3.59 ms -0.01 ms (-0.17%) 1.00%
handshake_no_resume_ring_1.3_ecdsap384_aes 3.60 ms 3.60 ms -0.01 ms (-0.17%) 1.00%
handshake_session_id_ring_1.3_ecdsap256_chacha 6.71 ms 6.70 ms -0.01 ms (-0.16%) 1.00%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_chacha 6.07 ms 6.06 ms -0.01 ms (-0.14%) 1.93%
handshake_tickets_ring_1.2_rsa_aes 1.64 ms 1.63 ms -0.00 ms (-0.13%) 1.25%
handshake_session_id_ring_1.3_ecdsap256_aes 6.75 ms 6.74 ms -0.01 ms (-0.12%) 1.00%
handshake_tickets_aws_lc_rs_1.3_rsa_chacha 6.30 ms 6.29 ms -0.01 ms (-0.12%) 1.84%
handshake_tickets_ring_1.3_ecdsap384_chacha 9.80 ms 9.81 ms 0.01 ms (0.11%) 1.00%
handshake_tickets_ring_1.3_rsa_aes 7.26 ms 7.26 ms -0.01 ms (-0.10%) 1.00%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_chacha 5.36 ms 5.35 ms -0.01 ms (-0.09%) 2.19%
handshake_tickets_ring_1.3_ecdsap256_aes 6.78 ms 6.77 ms -0.01 ms (-0.08%) 1.00%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_aes 5.36 ms 5.35 ms -0.00 ms (-0.08%) 2.38%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_aes 6.07 ms 6.07 ms -0.00 ms (-0.07%) 2.09%
handshake_tickets_ring_1.3_rsa_chacha 7.21 ms 7.21 ms -0.00 ms (-0.07%) 1.00%
handshake_tickets_ring_1.3_ecdsap256_chacha 6.73 ms 6.72 ms -0.00 ms (-0.04%) 1.00%
handshake_tickets_ring_1.3_ecdsap384_aes 9.85 ms 9.86 ms 0.00 ms (0.03%) 1.00%
handshake_session_id_ring_1.3_ecdsap384_chacha 9.79 ms 9.79 ms -0.00 ms (-0.02%) 1.00%
handshake_tickets_aws_lc_rs_1.3_rsa_aes 6.30 ms 6.30 ms -0.00 ms (-0.01%) 1.78%
handshake_session_id_ring_1.3_ecdsap384_aes 9.83 ms 9.83 ms 0.00 ms (0.01%) 1.00%

Additional information

Historical results

Checkout details:

cpu added 14 commits June 10, 2024 09:28
The SVCB/HTTPS record handling in hickory-dns 0.24 was stripping the TLS
encoded list prefix from the `ECHConfigList` that is serialized into DNS
records. This meant our previous `ech.rs` connect test was subtly wrong:
it would only ever deserialize a single `EchConfig` from what it found
in DNS.

This commit updates Rustls to:

1. Use the new `EchConfigListBytes` type from pki-types to represent
   what it gets from DNS. Soon we will have more API surface expecting
   this type.

2. Use a hickory-dns release with some upstream fixes that ensure we get
   the correct wire-encoding of the `ECHConfigList`.

3. Update the ech connect tests unit tests to assert all of the ECH
   configs that may be found are the correct version.
For ECH GREASE it's convenient to be able to generate throw-away HPKE
key-pairs. Similarly, down the road we may want to support generating
server-side ECH configurations, which will require key generation.

This commit updates the `Hpke` trait to add a `generate_key_pair()` fn
for this purpose. Both the aws-lc-rs and provider-example HPKE trait
impls are updated to add this functionality.

Along the way I also copied the smoke test and fips unit tests from the
aws-lc-rs HPKE provider to the provider-example HPKE provider so that
there's coverage of key generation for both. We won't use key generation
in the rustls-provider-tests crate since the RFC test vectors come with
private key material to use.
This commit introduces the first piece of ECH support to the public API:
configuring a client connection with an optional ECH config.

Since ECH requires TLS 1.3 we offer a configuration entry-point
`with_ech(...)` on the `ConfigBuilder<ClientConfig,
WantsVersions>` state, and fix the supported protocol versions to only
TLS 1.3.

Handling configurations in a way that will be forward compatible and
adhering to the draft spec requires some extra care. Notably we need to
be able to treat ECH configs in an ECH config list with an unsupported
version as opaque blobs. This requires splitting our config
representation into an enum with two variants: one for a recognized ECH
config and one for an unsupported one.

Similarly we need to process optional extensions in ECH config contents
to ensure that:

1. There MUST NOT be duplicate extensions.
2. We MUST parse and check for unsupported mandatory extensions.

An example TLS client that fetches ECH configurations using
DNS-over-HTTPS and configures Rustls to use ECH is added to the
examples crate. The HTTPS-over-DNS lookup in that example requires
adding a new dep on hickory-dns. We use the recently added aws-lc-rs
backed HPKE implementations default selection of HPKE suites for the ECH
config.

As of this commit the ECH configuration is not used (except as a TODO to
avoid a `dead_code` warning). Subsequent commits will introduce actual
ECH offering and protocol support.
In order to support ECH we need to be prepared for
`emit_client_hello_for_retry` to return an `Error` where it was
otherwise infallible - this can occur (for e.g.) if the HPKE provider we
use for ECH encryption fails.

This commit changes `emit_client_hello_for_retry` to return
`NextStateOrError` instead of `NextState` in preparation for that.
Previously we separately iterated the `input.hello.sent_extensions` to
track our sent extensions before constructing a `ClientHelloPayload`
that contained them. The `ClientHelloPayload` was constructed in-line
for the `HandshakeMessagePayload` towards the end of
`emit_client_hello_for_retry`.

To support ECH we will want to do some additional work with the
`ClientHelloPayload`, and so this commit does some minor rearranging to
facilitate this.
This commit continues the implementation of client-side ECH support. We
now act on the provided ECH configuration when available to produce an
appropriate outer/inner client hello.

Adding this support requires introduction of a new `EchState`
struct for maintaining the required handshake state specific to ECH. We
use this in combination with new types for representing the ECH
extensions to produce the outer and inner client hello messages.

We do not yet properly handle confirmation of ECH acceptance, resulting
in decrypt errors when offering ECH. Subsequent commits will update
hello retry request and server hello handling to fix this.
This commit continues the implementation of client-side ECH by
processing the result of offering ECH in the non-HRR case. This involves
processing the received server hello, attempting to derive and match
a shared secret indicating ECH acceptance, and forwarding on our
understanding of ECH status (not offered, offered and rejected, or
offered and accepted) to later steps of the handshake.

If we arrive at the end of the handshake and our ECH offer wasn't
accepted, then we emit an appropriate alert and return an error
potentially containing ECH configs to retry with from the server's
response.

If our offer _was_ accepted, we change out the handshake transcript,
sent extensions and client hello as if the inner client hello was used
as the outer client hello. TLS handshaking continues as normal from that
point.

This level of support is sufficient for the ech-client example to
successfully use ECH with the defo.ie test server.

Importantly we do **not** yet handle the case where we offer ECH and the
server sends a hello retry request. This support will follow in
a subsequent commit.
This commit continues the implementation of client-side ECH by
supporting the case where we offer ECH and the server replies with
a hello retry request (HRR).

In this case we detect ECH acceptance in a slightly different manner. If
ECH was accepted we update the separate ECH transcript using the
received HRR and proceed to offer ECH again in our retried hello. After
this point ECH acceptance is handled as normal.

This completes the primary functionality of client-side ECH. The
remaining work involves GREASE ECH and extension compression.
In the situation where an ECH config is not available some clients may
wish to send a "GREASE" ECH extension as an anti-ossification mechanism
(see RFC 8701[0] for more information on the general concept of GREASE).

To support this we update the configuration to accept an optional ECH
mode instead of an optional ECH config. The ECH mode has a variant for
enabling ECH that holds an ECH config, and a separate variant that holds
only what's required to emit a GREASE ECH extension.

We don't automatically fall back to GREASE if ECH configs are provided
but none are compatible. If desired this should be handled by the
caller. Similarly we don't default to sending GREASE, it is opt-in.

[0]: https://www.rfc-editor.org/rfc/rfc8701
* Use docopt to make it feasible to provide args/flags
* Add flags for choosing CA cert, DNS-over-HTTPS server, etc
* Add config for performing placeholder "GREASE" ECH for hosts without
  ECH configs, doing so by default for hosts without ECH configs, and
  forcing it if desired
* Add config flag for specifying a ECH config from disk.
* Add flag for specifying how many requests to do, to test resumption.
* Asserts on the expected ECH status after handshaking.
This matches the rustls crate's current default provider choice.
A `ClientConfig` can only be considered FIPS compatible when using ECH
if the configured HPKE suite is FIPS compatible. This commit updates
`ClientConfig::fips()` to add that consideration.

Similarly, it may be helpful to know if a given client connection was
created from a FIPS compatible `ClientConfig`. To do this we update the
client config data to stash the `ClientConfig::fips()` result when
creating a new client connection. A new `ClientConnection::fips()`
accessor returns that stashed value.
The bogo shim requires some updates to support new command line
flags. Additionally in order to be able to assert some details in errors
(e.g. that an ECH required err contained expected retry configs) we have
to pipe the `Options` struct deeper into the client/server processing
logic.

Since `*ring*` has no HPKE provider, it can't do ECH, which means we
need an unfortunate number of cfg guards on imports/logic in the shim
related to HPKE/ECH. C'est la vie. We can revisit if `*ring*` gains
static ECDH or HPKE.

Beyond these changes, it's worth discussing the ignored tests. They're
either not applicable, or need upstream bogo fixes:

"TLS-ECH-Server*":
  We ignore all the TLS-ECH-Server tests. We haven't implemented server
  side ECH yet

"TLS-ECH-Client-ExpectECHOuterExtensions"
"TLS-ECH-Client-CompressSupportedVersions":
  These rely on extension compression between inner/outer hellos. NYI.

"TLS-ECH-Client-SelectECHConfig"
"TLS-ECH-Client-NoSupportedConfigs"
  These are meant to test unsupported configs are handled correctly: we
  happen to support the HPKE ciphersuites that make them "unsupported".
  There's a fix for this upstream we can take later.

"TLS-ECH-Client-SkipInvalidPublicName*":
  Our name validation allows underscores in names. We also don't
  fallback to GREASE when there are no valid ECH configs.

"TLS-ECH-Client-NoSupportedConfigs-GREASE":
  We don't fallback to GREASE for no ECH configs.

"TLS-ECH-Client-Reject-ResumeInnerSession-TLS13":
  This test expects an unexpected extension error in the resumption
  connection, but this only happens if the outer hello didn't include
  GREASE PSK. BoringSSL's impl doesn't. Ours does. As a result we
  produce `:ECH_REJECTED:` instead of :UNEXPECTED_EXTENSION:` and have
  to ignore this test.

"TLS-ECH-Client-TLS12-RejectRetryConfigs"
"TLS-ECH-Client-Reject-NoClientCertificate-TLS12"
"TLS-ECH-Client-Reject-TLS12"
"TLS-ECH-Client-Reject-ResumeInnerSession-TLS12"
"TLS-ECH-GREASE-Client-TLS12-RejectRetryConfigs"
"TLS-ECH-Client-Reject-EarlyDataRejected-TLS12"
"TLS-ECH-Client-Reject-NoClientCertificate-TLS12-Async"
  We never offer/support TLS 1.2 when using ECH. There's no fallback to
  plaintext or GREASE for a server that won't support TLS 1.3
This avoids breaking our MSRV task due to the later versions of
hickory-dns (née trust-dns) that use workspace inheritance.
A workspace-level patch must be resolved even for crates that don't
require the patched dep, and resolving the patch for 0.22+ requires
an MSRV of 1.64+

This can be reverted if there's a finalized 0.25 with the SVCB fixes, or
a pre-release, made available.
@cpu
Copy link
Member Author

cpu commented Jun 10, 2024

@djc Do you think you'll have a chance to review this branch this week?

@djc
Copy link
Member

djc commented Jun 10, 2024

Yup! Sorry for not getting to it sooner, I'll keep it at the top of my list for today/tomorrow.

@cpu
Copy link
Member Author

cpu commented Jun 10, 2024

Thanks! Appreciated

@cpu
Copy link
Member Author

cpu commented Jun 10, 2024

The one remaining piece of work is to implement extension compression.

I have this work staged in a draft PR on my fork that targets this branch as its base.

Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, most of the core logic is over my head -- I don't have enough time/energy to fully digest it. But it looks well-designed, and I only have a few stylistic suggestions.

Ok(Self { config, suite })
}

fn select_config_and_suite(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this commit, it's not clear to me why making this a separate associated function is useful.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point; I will inline.

#[cfg(feature = "logging")]
use crate::log::{debug, warn};
use crate::msgs::codec::{Codec, Reader};
use crate::msgs::handshake::EchConfig as EchConfigMsg;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a strong reason to keep the two types with the same name? Maybe the msgs type should be called _Payload or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's a strong reason. I was trying to match to the names from draft-ietf-tls-esni-18 §4, but I think the enum arrangement already makes this not 1:1 with the simple presentation language in the spec.

Calling it EchConfigPayload sounds reasonable to me 👍 I will add a rename commit up-front and remove the aliased use's.

let _config = &ech_config.config;
Some(())
});
let ech_state = match config.ech_config.as_ref() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.map()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think it might make things more awkward? I can't use an if let / else to match the &EchMode given to the map closure because of MSRV, so I'd still need a match { } in the map body making it about the ~same amount of code, but more annoying to deal with the fallibility of the EchState::new().

Am I overthinking what you had in mind?

Comment on lines +76 to +77
ech_state: Option<EchState>,
server_hello_msg: &Message,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: feels like server_hello_msg should come earlier in this list? At least before ech_state, which seems like it would be longer lived.

@@ -146,6 +149,10 @@ pub(super) fn handle_server_hello(

let shared_secret = our_key_share.complete(&their_key_share.payload.0)?;

// TODO(@cpu): Handle confirmation of ECH.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed a while ago, I question the value of leaving these loose ends in main branch history (relative to squashing more things here).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the most awkward join point and it could be resolved by squashing the "ech: construct ECH client hello" commit with the subsequent "ech: confirm acceptance of ECH offer" commit.

I'll do that in the rebase that applies your feedback. 👍

@@ -1198,16 +1204,7 @@ pub struct ServerHelloPayload {

impl Codec<'_> for ServerHelloPayload {
fn encode(&self, bytes: &mut Vec<u8>) {
self.legacy_version.encode(bytes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, this is something I might do in a separate commit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'll end up with dead code warnings if I try to do that before implementing confirmation, or I'd have to implement a watered down version that only adds Encoding::Standard. In the latter case having that separated seems like it has less value. Do you feel strongly about this one?

confirmation_transcript.current_hash(),
);

Ok(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Same thing for the Ok-wrapping here.)

fn hello_retry_request_conf(retry_req: &HelloRetryRequest) -> Message {
Self::ech_conf_message(HandshakeMessagePayload {
typ: HandshakeType::HelloRetryRequest,
payload: HandshakePayload::HelloRetryRequest(retry_req.clone()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take the owned HelloRetryRequest?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will shake out the same as the server_hello_conf fn - see my reply there.

// See draft-ietf-tls-esni-18 7.2.1:
// <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-18#name-sending-helloretryrequest-2>
Encoding::EchConfirmation => {
let extensions = LengthPrefixedBuffer::new(ListLength::U16, bytes);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style nit: maybe take this out of the match arm?

// If we haven't offered ECH, and have no ECH state, then consider whether to use GREASE
// ECH.
(EchStatus::NotOffered, None) => {
if let Some(EchMode::Grease(grease_config)) = &config.ech_mode {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take this out of the match arm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Encrypted ClientHellos (ECH, formerly ESNI)
5 participants