Skip to content

perf: reuse hybrid key as standalone classical key share - #5989

Open
MrMistic wants to merge 1 commit into
aws:mainfrom
MrMistic:key-share-reuse
Open

perf: reuse hybrid key as standalone classical key share#5989
MrMistic wants to merge 1 commit into
aws:mainfrom
MrMistic:key-share-reuse

Conversation

@MrMistic

@MrMistic MrMistic commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

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_send sends 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 second EC_KEY keygen (~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" (see rustls/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 (via EVP_PKEY_up_ref for 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) and s2n_tls13_pq_handshake_test pass. 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

@MrMistic
MrMistic force-pushed the key-share-reuse branch 4 times, most recently from 4dd9817 to 7046739 Compare July 16, 2026 06:50
@MrMistic
MrMistic marked this pull request as ready for review July 16, 2026 17:40
@maddeleine

Copy link
Copy Markdown
Contributor

We have three different hybrid key share groups (X25519MLKEM768, SecP256r1MLKEM768, and SecP384r1MLKEM1024). Why is this PR only handling the X25519MLKEM768 case?

Comment thread tls/extensions/s2n_client_key_share.c Outdated
@MrMistic

Copy link
Copy Markdown
Contributor Author

We have three different hybrid key share groups (X25519MLKEM768, SecP256r1MLKEM768, and SecP384r1MLKEM1024). Why is this PR only handling the X25519MLKEM768 case?

Good point, I think I was getting tunnel vision on the x25519 part. Amended

@MrMistic MrMistic changed the title perf: reuse hybrid X25519 key as standalone classical key share perf: reuse hybrid key as standalone classical key share Jul 24, 2026
@MrMistic
MrMistic requested a review from maddeleine July 24, 2026 17:19
Comment thread tls/extensions/s2n_client_key_share.c
Comment thread tests/testlib/s2n_security_policy_testlib.c Outdated
@kaukabrizvi
kaukabrizvi self-requested a review August 6, 2026 22:05

@kaukabrizvi kaukabrizvi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There is currently no test asserting that this optimization actually occurs in practice. Could you add that?

@maddeleine

Copy link
Copy Markdown
Contributor

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.

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.

3 participants