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

Implement RFC 9180 HPKE provider backed by aws-lc-rs #1963

Merged
merged 13 commits into from
May 31, 2024

Conversation

cpu
Copy link
Member

@cpu cpu commented May 21, 2024

In order to support Encrypted Client Hello (ECH) we need a Hybrid Public Key Encryption (HPKE) provider (see RFC 9180). Previously we landed the traits required to abstract over an HPKE provider, and a proof-of-concept provider that used hpke-rs and Rust Crypto. In order to support HPKE in the base Rustls crate we need an HPKE provider backed by either aws-lc-rs, or *ring*.

Since static ECDH is not supported by *ring* (briansmith/ring#331), but is supported by aws-lc-rs (aws/aws-lc-rs#302) this branch implements an HPKE provider backed by aws-lc-rs. The existing test harness is moved to a new rustls-provider-test crate and lightly updated for pairwise interop testing between aws-lc-rs and the hpke-rs based provider-example impl.

Following the precedent set by the HPKE traits we landed, this is focused on only what is required for ECH. We don't implement any HPKE modes other than "base mode" (see RFC 9180 §5) , and don't offer export secrets.

The HPKE RFC requires some HKDF operations that previously weren't needed for TLS 1.3. Most notably, we need to be able to extract pseudo-random keys (PRKs) without immediately expanding them. The existing Hkdf trait, and the upstream implementations from aws-lc-rs and *ring* both encapsulate the PRK to prevent misuse, and so can't be used for this purpose. We work around this by adding a new HkdfPrkExtract trait that is a superset of Hkdf, offering a new extract_prk_from_secret() fn. We then implement this for the HMAC based HKDF impl from the tls13 package. This means the aws-lc-rs impl is tied to the HMAC based HKDF, but this doesn't seem to have any disadvantages in practice and the non-HMAC options can't support this operation without upstream changes.

Related to #1718

@cpu cpu self-assigned this May 21, 2024
Copy link

codecov bot commented May 21, 2024

Codecov Report

Attention: Patch coverage is 98.08362% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 93.94%. Comparing base (65d2e86) to head (1b4e071).
Report is 1 commits behind head on main.

Files Patch % Lines
provider-example/src/hpke.rs 75.00% 4 Missing ⚠️
rustls/src/crypto/hpke.rs 0.00% 3 Missing ⚠️
rustls/src/crypto/tls13.rs 81.25% 3 Missing ⚠️
rustls/src/crypto/aws_lc_rs/hpke.rs 99.81% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1963      +/-   ##
==========================================
- Coverage   95.54%   93.94%   -1.60%     
==========================================
  Files          86       95       +9     
  Lines       18728    19681     +953     
==========================================
+ Hits        17893    18489     +596     
- Misses        835     1192     +357     

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

@cpu cpu marked this pull request as draft May 21, 2024 20:27
Cargo.toml Outdated Show resolved Hide resolved
@cpu
Copy link
Member Author

cpu commented May 22, 2024

I'm reusing some general HKDF code from crate::crypto::tls13, but that means it's no longer TLS1.3 specific. Should these parts be lifted into a separate crate::crypto::hkdf module?

Thoughts on this? I'm leaning towards yes, as its own commit ahead of implementing HPKE. Edit: Consensus is to keep as-is.

@jplock
Copy link

jplock commented May 22, 2024

I’ve been interested in a HPKE implementation that is backed by aws-lc-rs. Will these structs and implementation be publicly accessible and usable even if I’m not interested in any other functionality in rustls?

I’ve been using hpke-rs with their RustCrypto provider but would be interested in switching.

@cpu
Copy link
Member Author

cpu commented May 22, 2024

Will these structs and implementation be publicly accessible and usable even if I’m not interested in any other functionality in rustls?

Yes, they're in the public API and should work in isolation with the caveat that only base mode is offered. If you need more modes/functionality writing an aws-lc-rs backend for hpke-rs is probably a better option.

@jplock
Copy link

jplock commented May 22, 2024

Base mode is all I’m interested in so this sounds great. Thank you!

@ctz
Copy link
Member

ctz commented May 23, 2024

Thoughts on this? I'm leaning towards yes, as its own commit ahead of implementing HPKE.

TLS1.3 requires HKDF, and HPKE/ECH requires TLS1.3, so I think it's reasonable if HKDF lives in the tls13 module. But that's not a strong objection if you prefer to move it.

@cpu cpu force-pushed the cpu-aws-lc-rs-hpke branch 2 times, most recently from 2b1af46 to cde04d3 Compare May 23, 2024 17:22
@cpu
Copy link
Member Author

cpu commented May 23, 2024

TLS1.3 requires HKDF, and HPKE/ECH requires TLS1.3, so I think it's reasonable if HKDF lives in the tls13 module

I find this a reasonable line of thinking and don't feel strongly. Leaving things as-is works for me.

cpu force-pushed the cpu-aws-lc-rs-hpke branch from 2b1af46 to cde04d3

The wonderful folks upstream cut a aws-lc-rs 1.7.2 release that pulls in a better fix for the HKDF info limit we were bumping into. I reworked this branch to take that update and simplified the testing workarounds I was using before.

@cpu cpu marked this pull request as ready for review May 23, 2024 20:05
@cpu
Copy link
Member Author

cpu commented May 23, 2024

cpu marked this pull request as ready for review now

I was able to knock out the one TODO I left myself to try and make the labelled expand step infallible. I think this is ready for a first review pass now.

The solution I arrived at for the above notches up the code complexity enough that I kept it in a separate commit at the end in case I'm on the wrong track. I think this is the first time I've used const generics in earnest and so expect there might be further tweaks needed.

rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/tests/hpke.rs Outdated Show resolved Hide resolved
Copy link

rustls-benchmarking bot commented May 24, 2024

Benchmark results

Instruction counts

Significant differences

⚠️ There are significant instruction count differences

Click to expand
Scenario Baseline Candidate Diff Threshold
handshake_no_resume_ring_1.3_ecdsap256_aes_server 2134354 2129565 -4789 (-0.22%) 0.20%

Other differences

Click to expand
Scenario Baseline Candidate Diff Threshold
handshake_session_id_aws_lc_rs_1.2_rsa_aes_server 3908230 3929658 21428 (0.55%) 7.05%
handshake_no_resume_aws_lc_rs_1.3_rsa_aes_server 13738446 13798902 60456 (0.44%) 0.84%
handshake_tickets_aws_lc_rs_1.2_rsa_aes_server 4377835 4392099 14264 (0.33%) 2.83%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_client 8710126 8736599 26473 (0.30%) 1.15%
transfer_no_resume_aws_lc_rs_1.3_rsa_aes_server 46437053 46329494 -107559 (-0.23%) 0.43%
handshake_tickets_aws_lc_rs_1.3_rsa_aes_server 33204207 33127912 -76295 (-0.23%) 0.70%
handshake_session_id_aws_lc_rs_1.3_rsa_aes_server 32931040 32859659 -71381 (-0.22%) 0.38%
handshake_no_resume_ring_1.3_ecdsap256_chacha_server 2131844 2135941 4097 (0.19%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_chacha_server 33137944 33084108 -53836 (-0.16%) 0.46%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_aes_client 8730856 8742633 11777 (0.13%) 0.81%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_aes_client 30780447 30749959 -30488 (-0.10%) 0.44%
handshake_no_resume_aws_lc_rs_1.2_rsa_aes_server 13374901 13386094 11193 (0.08%) 1.41%
transfer_no_resume_aws_lc_rs_1.2_rsa_aes_server 46423278 46384468 -38810 (-0.08%) 0.34%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_client 3383105 3380778 -2327 (-0.07%) 0.21%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_aes_client 30590097 30569218 -20879 (-0.07%) 0.43%
handshake_session_id_aws_lc_rs_1.2_rsa_aes_client 3970833 3973247 2414 (0.06%) 0.20%
handshake_session_id_aws_lc_rs_1.3_rsa_chacha_server 32837424 32856233 18809 (0.06%) 0.39%
handshake_session_id_ring_1.2_rsa_aes_client 4232541 4234754 2213 (0.05%) 0.20%
handshake_no_resume_ring_1.3_ecdsap256_aes_client 3916675 3914693 -1982 (-0.05%) 0.24%
handshake_session_id_ring_1.2_rsa_aes_server 4232921 4235034 2113 (0.05%) 0.20%
handshake_no_resume_ring_1.3_ecdsap256_chacha_client 3916236 3918108 1872 (0.05%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_aes_server 46430272 46408318 -21954 (-0.05%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_aes_server 46430110 46408299 -21811 (-0.05%) 0.20%
handshake_tickets_ring_1.2_rsa_aes_client 4506701 4508709 2008 (0.04%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_chacha_client 30561496 30575090 13594 (0.04%) 0.33%
transfer_no_resume_ring_1.3_rsa_aes_server 46461789 46445046 -16743 (-0.04%) 0.20%
handshake_tickets_aws_lc_rs_1.2_rsa_aes_client 4298659 4300203 1544 (0.04%) 0.20%
transfer_no_resume_ring_1.2_rsa_aes_server 46361962 46345375 -16587 (-0.04%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_aes_server 46457291 46440863 -16428 (-0.04%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_client 92666491 92694624 28133 (0.03%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_chacha_server 32863289 32853369 -9920 (-0.03%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_aes_server 32903561 32894253 -9308 (-0.03%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_aes_server 32903603 32894431 -9172 (-0.03%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_server 80609251 80587195 -22056 (-0.03%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_server 80609134 80587097 -22037 (-0.03%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_aes_client 30608110 30599866 -8244 (-0.03%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_chacha_server 32862142 32853851 -8291 (-0.03%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_aes_server 46448786 46437435 -11351 (-0.02%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_chacha_server 33139151 33131317 -7834 (-0.02%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_chacha_server 33138489 33131377 -7112 (-0.02%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_aes_server 33162990 33155940 -7050 (-0.02%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_aes_server 33162751 33155957 -6794 (-0.02%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_chacha_server 43312089 43303891 -8198 (-0.02%) 0.20%
handshake_session_id_aws_lc_rs_1.3_rsa_aes_client 30621124 30615695 -5429 (-0.02%) 0.20%
handshake_no_resume_ring_1.2_rsa_aes_client 2856052 2856550 498 (0.02%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_rsa_chacha_server 80602762 80615899 13137 (0.02%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_chacha_client 30801429 30796485 -4944 (-0.02%) 0.20%
handshake_session_id_aws_lc_rs_1.3_rsa_chacha_client 30595529 30590649 -4880 (-0.02%) 0.20%
handshake_tickets_ring_1.2_rsa_aes_server 4664992 4665703 711 (0.02%) 0.20%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_chacha_client 30582069 30577573 -4496 (-0.01%) 0.20%
handshake_tickets_aws_lc_rs_1.3_rsa_aes_client 30824787 30820261 -4526 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_chacha_client 41770700 41764791 -5909 (-0.01%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_server 1913414 1913147 -267 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_aes_client 41854192 41848447 -5745 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap256_aes_server 43688533 43694525 5992 (0.01%) 0.20%
handshake_tickets_ring_1.3_rsa_chacha_client 41984792 41979264 -5528 (-0.01%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_chacha_client 30760662 30756769 -3893 (-0.01%) 0.33%
handshake_session_id_ring_1.3_rsa_aes_server 43410894 43405467 -5427 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_aes_server 43413071 43407650 -5421 (-0.01%) 0.20%
handshake_session_id_ring_1.3_rsa_aes_client 41866001 41860836 -5165 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap256_aes_server 43412942 43408107 -4835 (-0.01%) 0.20%
handshake_session_id_ring_1.3_rsa_chacha_client 41784545 41780175 -4370 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap256_chacha_server 43617040 43612603 -4437 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_aes_client 42036109 42032075 -4034 (-0.01%) 0.20%
handshake_session_id_ring_1.3_rsa_chacha_server 43309525 43305485 -4040 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_aes_client 41847339 41843458 -3881 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_chacha_client 41766068 41762301 -3767 (-0.01%) 0.20%
handshake_tickets_ring_1.3_rsa_aes_server 43690973 43687199 -3774 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_chacha_client 41966086 41962505 -3581 (-0.01%) 0.20%
handshake_tickets_ring_1.3_rsa_aes_client 42053692 42050228 -3464 (-0.01%) 0.20%
handshake_session_id_ring_1.3_ecdsap384_chacha_server 43311973 43308492 -3481 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap256_chacha_client 41968378 41965086 -3292 (-0.01%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_chacha_client 30783643 30781501 -2142 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_aes_server 43692875 43689885 -2990 (-0.01%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_chacha_server 80506700 80501242 -5458 (-0.01%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_aes_client 2224815 2224683 -132 (-0.01%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_chacha_server 4290184 4289947 -237 (-0.01%) 0.20%
handshake_tickets_ring_1.3_ecdsap384_chacha_server 43618098 43615810 -2288 (-0.01%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_chacha_client 2232238 2232122 -116 (-0.01%) 0.20%
handshake_no_resume_ring_1.3_rsa_chacha_client 2955147 2955288 141 (0.00%) 0.20%
handshake_no_resume_aws_lc_rs_1.2_rsa_aes_client 2014980 2015075 95 (0.00%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_aes_server 1910074 1909984 -90 (-0.00%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_rsa_chacha_server 13782393 13783039 646 (0.00%) 0.76%
handshake_tickets_ring_1.3_ecdsap256_aes_client 42039025 42040813 1788 (0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_aes_client 58315293 58317507 2214 (0.00%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_aes_client 3380642 3380526 -116 (-0.00%) 0.31%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_chacha_client 92689615 92692677 3062 (0.00%) 0.20%
handshake_tickets_ring_1.3_rsa_chacha_server 43615547 43614594 -953 (-0.00%) 0.20%
handshake_no_resume_ring_1.3_rsa_aes_server 12168190 12168423 233 (0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_aes_client 58231019 58232049 1030 (0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_chacha_server 80510423 80509091 -1332 (-0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_aes_client 58199588 58198721 -867 (-0.00%) 0.20%
handshake_no_resume_ring_1.2_rsa_aes_server 11985005 11985170 165 (0.00%) 0.20%
handshake_no_resume_ring_1.3_rsa_chacha_server 12174199 12174042 -157 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_rsa_chacha_server 80514627 80513735 -892 (-0.00%) 0.20%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_aes_server 4286542 4286586 44 (0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_aes_server 13737752 13737640 -112 (-0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_aes_client 35471580 35471868 288 (0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_chacha_server 13739846 13739940 94 (0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_rsa_chacha_client 92691009 92691631 622 (0.00%) 0.20%
handshake_no_resume_ring_1.3_rsa_aes_client 2949471 2949454 -17 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_rsa_aes_client 58318662 58318350 -312 (-0.00%) 0.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_aes_client 30802013 30802176 163 (0.00%) 0.20%
transfer_no_resume_ring_1.2_rsa_aes_client 58200888 58200609 -279 (-0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.3_rsa_aes_client 58233619 58233836 217 (0.00%) 0.20%
transfer_no_resume_aws_lc_rs_1.2_rsa_aes_client 68654069 68653974 -95 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_chacha_client 92647082 92647010 -72 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap384_aes_client 58315363 58315335 -28 (-0.00%) 0.20%
transfer_no_resume_ring_1.3_rsa_chacha_client 92651369 92651406 37 (0.00%) 0.20%
transfer_no_resume_ring_1.3_ecdsap256_chacha_client 92648542 92648519 -23 (-0.00%) 0.20%
handshake_no_resume_ring_1.3_ecdsap384_chacha_client 35473907 35473899 -8 (-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_aws_lc_rs_1.3_rsa_aes 1.41 ms 1.43 ms ⚠️ 0.02 ms (1.43%) 1.26%

Other differences

Click to expand
Scenario Baseline Candidate Diff Threshold
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_aes 4.46 ms 4.58 ms 0.12 ms (2.62%) 6.16%
transfer_no_resume_aws_lc_rs_1.3_rsa_aes 5.40 ms 5.53 ms 0.13 ms (2.39%) 4.79%
transfer_no_resume_aws_lc_rs_1.2_rsa_aes 5.40 ms 5.52 ms 0.12 ms (2.30%) 4.05%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_aes 5.18 ms 5.29 ms 0.11 ms (2.17%) 5.47%
transfer_no_resume_ring_1.3_ecdsap256_aes 6.29 ms 6.39 ms 0.10 ms (1.67%) 4.09%
transfer_no_resume_ring_1.2_rsa_aes 6.70 ms 6.80 ms 0.10 ms (1.49%) 3.31%
transfer_no_resume_ring_1.3_rsa_aes 6.78 ms 6.89 ms 0.10 ms (1.48%) 3.55%
handshake_no_resume_aws_lc_rs_1.3_rsa_chacha 1.40 ms 1.42 ms 0.02 ms (1.39%) 1.49%
handshake_no_resume_ring_1.3_ecdsap256_aes 501.77 µs 508.48 µs 6.70 µs (1.34%) 2.47%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_chacha 476.64 µs 482.76 µs 6.12 µs (1.29%) 2.72%
handshake_no_resume_aws_lc_rs_1.2_rsa_aes 1.35 ms 1.37 ms 0.02 ms (1.28%) 1.35%
handshake_no_resume_ring_1.3_ecdsap256_chacha 499.80 µs 506.15 µs 6.35 µs (1.27%) 2.69%
transfer_no_resume_ring_1.3_ecdsap384_aes 9.38 ms 9.49 ms 0.11 ms (1.16%) 2.74%
handshake_no_resume_aws_lc_rs_1.3_ecdsap256_aes 477.93 µs 483.12 µs 5.19 µs (1.09%) 2.32%
handshake_session_id_aws_lc_rs_1.2_rsa_aes 2.05 ms 2.07 ms 0.02 ms (1.04%) 1.51%
transfer_no_resume_aws_lc_rs_1.3_ecdsap256_chacha 12.92 ms 13.05 ms 0.13 ms (0.98%) 2.23%
handshake_tickets_ring_1.2_rsa_aes 1.63 ms 1.64 ms 0.02 ms (0.97%) 1.17%
transfer_no_resume_ring_1.3_ecdsap256_chacha 12.92 ms 13.05 ms 0.13 ms (0.97%) 1.97%
transfer_no_resume_aws_lc_rs_1.3_rsa_chacha 13.87 ms 13.99 ms 0.13 ms (0.93%) 1.73%
transfer_no_resume_aws_lc_rs_1.3_ecdsap384_chacha 13.63 ms 13.75 ms 0.12 ms (0.90%) 2.08%
transfer_no_resume_ring_1.3_rsa_chacha 13.43 ms 13.54 ms 0.12 ms (0.87%) 1.81%
transfer_no_resume_ring_1.3_ecdsap384_chacha 16.03 ms 16.15 ms 0.12 ms (0.74%) 1.57%
handshake_tickets_aws_lc_rs_1.2_rsa_aes 2.22 ms 2.24 ms 0.02 ms (0.72%) 1.75%
handshake_no_resume_ring_1.2_rsa_aes 974.53 µs 979.18 µs 4.65 µs (0.48%) 1.00%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_chacha 5.40 ms 5.37 ms -0.02 ms (-0.46%) 1.16%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_chacha 6.11 ms 6.08 ms -0.03 ms (-0.44%) 1.20%
handshake_tickets_aws_lc_rs_1.3_ecdsap384_aes 6.12 ms 6.09 ms -0.03 ms (-0.44%) 1.00%
handshake_tickets_aws_lc_rs_1.3_ecdsap256_aes 5.40 ms 5.38 ms -0.02 ms (-0.43%) 1.27%
handshake_session_id_ring_1.2_rsa_aes 1.55 ms 1.56 ms 0.01 ms (0.40%) 1.09%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_chacha 5.37 ms 5.35 ms -0.02 ms (-0.38%) 1.26%
handshake_session_id_aws_lc_rs_1.3_ecdsap256_aes 5.38 ms 5.36 ms -0.02 ms (-0.36%) 1.27%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_chacha 1.18 ms 1.19 ms 0.00 ms (0.34%) 1.18%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_aes 6.10 ms 6.08 ms -0.02 ms (-0.32%) 1.05%
handshake_session_id_aws_lc_rs_1.3_ecdsap384_chacha 6.07 ms 6.05 ms -0.02 ms (-0.30%) 1.34%
handshake_no_resume_ring_1.3_rsa_chacha 1.00 ms 1.00 ms 0.00 ms (0.30%) 1.00%
handshake_no_resume_ring_1.3_ecdsap384_chacha 3.60 ms 3.61 ms 0.01 ms (0.29%) 1.00%
handshake_no_resume_ring_1.3_ecdsap384_aes 3.60 ms 3.61 ms 0.01 ms (0.25%) 1.00%
handshake_no_resume_ring_1.3_rsa_aes 997.00 µs 999.40 µs 2.40 µs (0.24%) 1.00%
handshake_tickets_ring_1.3_ecdsap256_aes 6.73 ms 6.74 ms 0.01 ms (0.18%) 1.00%
handshake_session_id_ring_1.3_ecdsap256_aes 6.70 ms 6.71 ms 0.01 ms (0.18%) 1.00%
handshake_session_id_ring_1.3_ecdsap384_aes 9.79 ms 9.80 ms 0.01 ms (0.15%) 1.00%
handshake_tickets_ring_1.3_rsa_aes 7.22 ms 7.23 ms 0.01 ms (0.14%) 1.00%
handshake_session_id_ring_1.3_rsa_aes 7.20 ms 7.21 ms 0.01 ms (0.12%) 1.00%
handshake_tickets_ring_1.3_ecdsap384_aes 9.82 ms 9.83 ms 0.01 ms (0.11%) 1.00%
handshake_tickets_aws_lc_rs_1.3_rsa_aes 6.34 ms 6.34 ms -0.01 ms (-0.11%) 1.25%
handshake_session_id_ring_1.3_ecdsap256_chacha 6.68 ms 6.68 ms -0.00 ms (-0.05%) 1.00%
handshake_tickets_ring_1.3_ecdsap384_chacha 9.78 ms 9.79 ms 0.00 ms (0.05%) 1.00%
handshake_session_id_ring_1.3_ecdsap384_chacha 9.76 ms 9.77 ms 0.00 ms (0.04%) 1.00%
handshake_tickets_ring_1.3_rsa_chacha 7.19 ms 7.19 ms 0.00 ms (0.04%) 1.00%
handshake_no_resume_aws_lc_rs_1.3_ecdsap384_aes 1.19 ms 1.19 ms 0.00 ms (0.04%) 1.00%
handshake_tickets_aws_lc_rs_1.3_rsa_chacha 6.34 ms 6.34 ms -0.00 ms (-0.03%) 1.28%
handshake_tickets_ring_1.3_ecdsap256_chacha 6.70 ms 6.70 ms 0.00 ms (0.03%) 1.00%
handshake_session_id_aws_lc_rs_1.3_rsa_aes 6.33 ms 6.33 ms -0.00 ms (-0.02%) 1.04%
handshake_session_id_aws_lc_rs_1.3_rsa_chacha 6.31 ms 6.31 ms -0.00 ms (-0.02%) 1.42%
handshake_session_id_ring_1.3_rsa_chacha 7.17 ms 7.17 ms 0.00 ms (0.01%) 1.00%

Additional information

Historical results

Checkout details:

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!

Cargo.lock Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
provider-example/tests/hpke.rs Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
@cpu
Copy link
Member Author

cpu commented May 24, 2024

Thank you both for the reviews! I will start working through the feedback.

@cpu
Copy link
Member Author

cpu commented May 24, 2024

cpu force-pushed the cpu-aws-lc-rs-hpke branch from 4bce613 to afd9a00

I believe I've addressed all the feedback. Thank you, the current state is a nice improvement over my first draft.

@ctz I'm going to dismiss your review since there's been substantial change. If you could re- 🔍 I'd appreciate it.

The solution I arrived at for the above notches up the code complexity enough that I kept it in a separate commit at the end in case I'm on the wrong track.

Since it seems like everyone liked the const-ified version I squashed it down into the initial implementation commit.

rustls / Build+test (nightly, ubuntu-latest) (pull_request) Failing after 3m

See rust-lang/rust#125474

@cpu cpu requested review from ctz and djc May 24, 2024 20:22
@cpu
Copy link
Member Author

cpu commented May 29, 2024

I'd like to use more of the test vectors (e.g. matching our produced ciphertexts with the expected values).

Done. I tried a few different approaches before settling on the one I pushed in 81ae6ae - I think it's the least invasive solution but would be open to alternatives if anyone has smarter ideas.

Some notes about the new test:

  • We're now matching the Enc returned from creating a Sealer, and the ciphertext returned from using it to seal the test vector plaintext with the test vector expected values.
  • I didn't make the even more invasive changes that would be required to match intermediate values (base_nonce, shared_secret, key_schedule_context, etc) with the test vector values. I don't think there's much value here since we're now matching the user-facing values that are produced using those intermediates. If we messed something up with the intermediate values the things we are asserting on would be wrong.
  • We end up duplicating a little bit of test scaffolding between the aws-lc-rs unit test and the rustls-provider-test integration test but it felt reasonable and I don't know there's a better way - I really don't want to make the ability to fiddle with the DH KEM available outside of the core crate.

I want to get the ECH branch rebased and passing the bogo suite using this HPKE provider before we merge.

Done: cpu-aws-lc-rs-hpke-client-ech - I haven't pushed an update to the PR branch yet (need to sort out BOGO w/ ring skipping ECH tests) but it works in the aws-lc-rs case (meaning we have HPKE interop with a 3rd Go based impl) and against some of the test servers (themselves using a 4th HPKE impl).

Going to flip this out of draft status. I think it's ready to merge as soon as reviewers are happy.

@cpu cpu marked this pull request as ready for review May 29, 2024 20:08
@cpu cpu requested review from djc and ctz May 29, 2024 20:08
provider-example/src/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/tls13.rs Show resolved Hide resolved
rustls/src/crypto/ring/hmac.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
rustls/src/crypto/aws_lc_rs/hpke.rs Outdated Show resolved Hide resolved
@djc
Copy link
Member

djc commented May 30, 2024

Great work!

@cpu cpu force-pushed the cpu-aws-lc-rs-hpke branch 2 times, most recently from 6d1401c to d2a0b08 Compare May 30, 2024 14:16
cpu added 13 commits May 30, 2024 10:27
This will make it easier to drop the `HpkeProvider` trait. The only
implementation, in the `provider-example` crate, is reworked to support
the new trait fn. We can make this breaking change without worrying
about semver because the `crypto::hpke` module is docs-hidden and has
been considered an internal unstable API.

This change also allows deriving `Debug` for the provider example
`HpkeRs` struct.
Requiring this was a quirk of the hpke-rs backed impl in the provider
crate. With the latest rework to store just the `HpkeSuite` this isn't
required anymore. State isn't introduced until a `Sealer`/`Opener` are
created. Similarly, our forthcoming `aws-lc-rs` HPKE impl requires no
mutability for these trait fns. Like before we can make breaking changes
here because the `crypto::hpke` module is docs-hidden.
It's useful to be able to check these for equality, and all of the field
members are themselves `Eq` and `PartialEq`, making this easy to
achieve.
With more experience we've discovered the `HpkeProvider` trait isn't
required. We can instead get away with having a slice of supported `&dyn
Hpke` instances. To facilitate finding a supported suite from that slice
a newtype wrapper (`HpkeSuites`) is offered with a `supported()` fn to
handle this task. The existing `provider-example` implementation and
tests are updated accordingly.
Adds a `fips()` fn to the `Hpke` trait, and a default implementation
that returns false.
The existing `Hkdf` trait is well suited to the TLS 1.3 use-case where
all pseudo-random keys (PRKs) extracted using HKDF are only used for an
as-is expansion. In this context the PRK is encapsulated in an
`HkdfExpander`, and not accessible directly to callers (helping to avoid
misuse).

In other contexts, notably HPKE, we need to use an HKDF to expand two
PRKs that are combined with some other metadata before being used for an
expansion. This requires direct access to the PRK bytes, and so can't be
done with the existing traits.

This commit adds a new `HkdfPrkExpand` trait that uses the existing
`Hkdf` trait as a super-trait. It adds one new fn,
`extract_prk_from_secret`, that returns the raw PRK. We implement this
trait for the `HkdfExpanderUsingHmac` type (and can reuse the code in
the existing `Hkdf::extract_from_zero_ikm` and
`Hkdf::extract_from_secret` fns that need a PRK.

We can't implement this trait for the upstream Ring/aws-lc-rs `RingHkdf`
types, as these use an opaque upstream `Prk` type tailored to the
extract-and-then-expand usecase. Since a HMAC based HKDF is sufficient
for the current needs and implementing the new trait requires no upstream
changes we prefer this approach.
This allows users of aws-lc-rs to build HMAC HKDF constructions using
the ring-like HMAC algorithms.
Now that we'll be using these HMAC algorithms from the aws-lc-rs HPKE
implementation they should be made available to reference without
needing the `tls12` feature enabled. Similarly the `HMAC_SHA512`
algorithm should now be usable outside of test contexts.
This commit introduces a minimal RFC 9180 "Hybrid Public Key Encryption"
(HPKE) implementation using crypto primitives (ECDH, HKDF, AEAD) from
the `aws-lc-rs` crate.

Our implementation is tailored towards the needs of Encrypted Client
Hello (ECH) and so:

1. We only implement "base mode" HPKE.
2. We don't implement the secret export support.

Care is taken to ensure the implementation is "linker friendly"
- unreferenced algorithms will be discarded by the linker.
Now that we have an "in-house" implementation of the HPKE traits (via
`crypto::aws_lc_rs::hpke` it feels like time to un-hide this module.
As an initial starting point, test that the aws-lc-rs HPKE suites from
the main rustls crate and the hpke-rs HPKE suites from the
provider-example crate can interoperate.

This process is slower (~30s) so having the tests in a separate crate is
helpful. It also allows us to take heavier deps (like the
provider-example crate, hpke-rs and rust crypto).
This commit implements a better testing strategy using the RFC 9180 test
vectors. Unlike the `rustls-provider-test` test, this version matches
the produced `EncapsulatedSecret` and ciphertext values from a `Seal`
operation against the expected values from the RFC.

We don't do this in the integration test because it requires overriding
the DH KEM so that it doesn't produce a randomly generated ephemeral
private key during the `Encap` operation. This is obviously not
something we want to support in normal usage and so requires some care.

To achieve this we introduce a test-only constructor for the aws-lc-rs
based `Sealer` that can pass through the pre-specified `skE` to
a special test-only DH KEM `Encap` that will use it instead of
generating one.

These test only functions are not exported, and so we make use of them
from a unit test in the same module. This results in some mild
duplication of the test vector supporting code, but seems like the best
trade-off.

We continue to ignore the test vector `shared_secret`,
`key_schedule_context`, `secret`, `key`, and `base_nonce` values:
exposing these for test interrogation will require even more gross
test-only contortions and if we've gotten these intermediate values
wrong, the `enc` and `ct` values we _are_ matching would be off, or the
unseal would break.
@cpu cpu dismissed ctz’s stale review May 30, 2024 18:35

some substantial changes since approval

@cpu
Copy link
Member Author

cpu commented May 30, 2024

@ctz If you have a chance I'd love another review pass on this branch. I dismissed your +1 from earlier because of the changes that landed since.

rustls/src/crypto/aws_lc_rs/hpke.rs Show resolved Hide resolved
@cpu cpu added this pull request to the merge queue May 31, 2024
Merged via the queue into rustls:main with commit 835c17c May 31, 2024
24 of 25 checks passed
@cpu cpu deleted the cpu-aws-lc-rs-hpke branch May 31, 2024 13:04
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.

4 participants