perf: reuse hybrid key as standalone classical key share - #5989
Conversation
4dd9817 to
7046739
Compare
|
We have three different hybrid key share groups (X25519MLKEM768, SecP256r1MLKEM768, and SecP384r1MLKEM1024). Why is this PR only handling the X25519MLKEM768 case? |
7046739 to
6cbde1c
Compare
Good point, I think I was getting tunnel vision on the x25519 part. Amended |
6cbde1c to
855bb08
Compare
855bb08 to
32f8705
Compare
kaukabrizvi
left a comment
There was a problem hiding this comment.
There is currently no test asserting that this optimization actually occurs in practice. Could you add that?
Yeah, I think you should write a test that shows that in this scenario where the security policy allows it, the key in the hybrid keyshare and the key in the classical keyshare are identical. And then vice versa, when the security policy disallows it (i.e. when the classical group does not match the group in the hybrid keyshare), the keyshares don't match. |
32f8705 to
56d0513
Compare
Goal
When a TLS 1.3 client offers the X25519MLKEM768 PQ hybrid key share, reuse the X25519 key it already generated as the standalone classical key share, instead of generating a separate P-256 key.
Why
s2n_client_key_share_sendsends two key shares: the PQ hybrid (X25519MLKEM768, which internally generates an X25519 ephemeral key) and a standalone classical share. Today the classical share is a freshly generated P-256 key. This is a secondEC_KEYkeygen (~10µs) even though an X25519 key was just created inside the hybrid. rustls avoids this by sending the hybrid's X25519 component as the second KeyShareEntry "for free" (seerustls/src/client/hs.rs).How
In
s2n_generate_default_ecc_key_share, when the negotiated hybrid already produced an X25519 key and the security policy's ECC preference list includes X25519, reuse that key (viaEVP_PKEY_up_reffor refcount-safe sharing) as the standalone share rather than generating a fresh P-256 key. Otherwise, fall back to the existing behavior (ecc_curves[0]).Callouts
This changes the wire for affected policies from
[X25519MLKEM768, P-256]to[X25519MLKEM768, X25519]. The client offers the same X25519 public key in both the hybrid and standalone KeyShareEntry; these are distinct groups (different IANA ids) and the server selects exactly one, so the private key is used in at most one shared-secret computation (no cross-group key reuse).Measured benefit: ~10µs saved (one P-256 keygen eliminated) on my machine, from 662us to 652us. This is consistent with the CLIENT_HELLO delta vs rustls, which was originally ~42us for s2n and ~31us for rustls.
Testing
s2n_client_key_share_extension_test(443 tests) ands2n_tls13_pq_handshake_testpass. The PQ handshake test confirms the reuse path fires for X25519MLKEM768 and correctly falls back for SecP256r1MLKEM768 / SecP384r1MLKEM1024. Full TLS 1.3 handshake tests pass on OpenSSL 3.x and AWS-LC, including the classical-fallback path.Related
Longer writeup