Skip to content

8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange - #662

Open
rm-gh-8 wants to merge 1 commit into
openjdk:masterfrom
rm-gh-8:JDK-8314323-V25
Open

8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange#662
rm-gh-8 wants to merge 1 commit into
openjdk:masterfrom
rm-gh-8:JDK-8314323-V25

Conversation

@rm-gh-8

@rm-gh-8 rm-gh-8 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Backporting JDK-8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange.

This PR adds ML-KEM and hybrid post-quantum key exchange support to the JSSE provider.

This PR is not clean because it skips JDK-8372004 (introduces a large dependency graph), which affects KeyShareExtension.java. However, the conflict only requires minor adjustments (specifically using isOn instead of the isOn() method, which is not available).

For parity with Oracle JDK.

Ran related tests on linux-x64, linux-aarch64, macos-aarch64 and windows-x64:

make test TEST=test/jdk/javax/net/ssl

make test TEST=test/jdk/sun/security

Results:

windows-x64-specific-test.log
windows-x64-specific-2-test.log
macos-aarch64-specific-test.log
macos-aarch64-specific-2-test.log
linux-x64-specific-test.log
linux-x64-specific-2-test.log
linux-aarch64-specific-test.log
linux-aarch64-specific-2-test.log

Ran related benchmarks on windows-x64, linux-x64, linux-aarch64, and macos-aarch64:

./build/*/images/jdk/bin/java -jar build/*/images/test/micro/benchmarks.jar org.openjdk.bench.java.security.SSLHandshake

./build/*/images/jdk/bin/java -jar build/*/images/test/micro/benchmarks.jar org.openjdk.bench.javax.crypto.full.KEMBench

./build/*/images/jdk/bin/java -jar build/*/images/test/micro/benchmarks.jar org.openjdk.bench.javax.crypto.full.KeyPairGeneratorBench

Results:

windows-x64-benchmark-test.log
windows-x64-benchmark-2-test.log
windows-x64-benchmark-3-test.log
macos-aarch64-benchmark-test.log
macos-aarch64-benchmark-2-test.log
macos-aarch64-benchmark-3-test.log
linux-x64-benchmark-test.log
linux-x64-benchmark-2-test.log
linux-x64-benchmark-3-test.log
linux-aarch64-benchmark-test.log
linux-aarch64-benchmark-2-test.log
linux-aarch64-benchmark-3-test.log

Risk Analysis: High - This is a security critical change that can potentially cause breaking interoperability with other TLS stacks and regressions to existing ECDHE/FFDHE handshakes



Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change requires CSR request JDK-8384361 to be approved
  • Change must be properly reviewed (4 reviews required, with at least 1 Reviewer, 3 Authors)
  • JDK-8314323 needs maintainer approval

Issues

  • JDK-8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange (Enhancement - P2 - Approved)
  • JDK-8384361: Implement JEP 527: TLS 1.3 Hybrid Key Exchange (CSR)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk25u-dev.git pull/662/head:pull/662
$ git checkout pull/662

Update a local copy of the PR:
$ git checkout pull/662
$ git pull https://git.openjdk.org/jdk25u-dev.git pull/662/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 662

View PR using the GUI difftool:
$ git pr show -t 662

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk25u-dev/pull/662.diff

Using Webrev

Link to Webrev Comment

@rm-gh-8
rm-gh-8 marked this pull request as ready for review July 14, 2026 15:12
@bridgekeeper

bridgekeeper Bot commented Jul 14, 2026

Copy link
Copy Markdown

👋 Welcome back rmesde! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk

openjdk Bot commented Jul 14, 2026

Copy link
Copy Markdown

@rm-gh-8 This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange

Reviewed-by: stooke, simonis, andrew, sgehwolf

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 27 new commits pushed to the master branch:

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk Bot changed the title Backport 21dc41f744edd138e77970d4e25e3a7eda41621f 8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange Jul 14, 2026
@openjdk

openjdk Bot commented Jul 14, 2026

Copy link
Copy Markdown

This backport pull request has now been updated with issue from the original commit.

@openjdk openjdk Bot added backport Port of a pull request already in a different code base rfr Pull request is ready for review labels Jul 14, 2026
@mlbridge

mlbridge Bot commented Jul 14, 2026

Copy link
Copy Markdown

Webrevs

@jerboaa

jerboaa commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

@stooke Please take a look.

@jerboaa

jerboaa commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

/reviewers 2

@openjdk

openjdk Bot commented Jul 14, 2026

Copy link
Copy Markdown

@jerboaa
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 1 Reviewer, 1 Author).

@stooke stooke left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

(disclaimer: I am not an OpenJDK reviewer)
I have been working on this patch too and my version, is identical give or take one whitespace line in FipsModeTLS.java.
As such, I have confidence in it so I say it looks good to me.

@jerboaa

jerboaa commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

I'd like to review and test this myself too. ETA, a couple of days.

@simonis simonis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @rm-gh-8 , the backport looks good. Is my understanding correct that you only ran the JMH benchmarks after the downport? How can we compare this to the performance results before the downport to ensure that the downport doesn't introduce any regression?

At a first glance, the downport introduces some new benchmarks so you probably can't easily run the new benchmarks with the old JDK, but maybe you can run the old benchmarks with the new code? It would definitely be nice to have at least some comparison between the two versions (and doing this comparison on Linux/x64/aarch64 would be enough).

@gnu-andrew gnu-andrew left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The patch itself looks near-clean and I agree that JDK-8372004, while caught in the context of this change, is unrelated.

The patch doesn't touch any API classes and so is safe for backport from trunk in that respect. I verified that the old codepaths are still present as is (if refactored) when not using hybrid exchange.

The main risk to be aware of is X25519MLKEM768 being added to the top of the default named groups where it will now take precedence over x25519 alone. However, there is a user-accessible workaround for this by setting custom named groups with jdk.tls.namedGroups. The other two algorithms have to be explicitly requested.

I think @franferrax should look this one over too.

/reviewers 4

@openjdk

openjdk Bot commented Jul 15, 2026

Copy link
Copy Markdown

⚠️ @rm-gh-8 This change is now ready for you to apply for maintainer approval. This can be done directly in each associated issue or by using the /approval command.

@openjdk

openjdk Bot commented Jul 15, 2026

Copy link
Copy Markdown

@gnu-andrew
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 4 (with at least 1 Reviewer, 3 Authors).

@gnu-andrew

Copy link
Copy Markdown
Member

Thanks @rm-gh-8 , the backport looks good. Is my understanding correct that you only ran the JMH benchmarks after the downport? How can we compare this to the performance results before the downport to ensure that the downport doesn't introduce any regression?

At a first glance, the downport introduces some new benchmarks so you probably can't easily run the new benchmarks with the old JDK, but maybe you can run the old benchmarks with the new code? It would definitely be nice to have at least some comparison between the two versions (and doing this comparison on Linux/x64/aarch64 would be enough).

The benchmark changes add a new case using the new provider, so yes, that case would fail if the new tests were run on the old code. I agree it would be useful to compare the benchmarks from the unpatched code on both patched and unpatched builds to ensure the change has not caused a noticeable slowdown in the old key exchange mechanisms.

@rm-gh-8

rm-gh-8 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

@simonis and @gnu-andrew , as requested, here are the findings from running the old (unpatched) benchmarks on both the unpatched and patched codebases (linux-x64).

./build/*/images/jdk/bin/java -jar build/*/images/test/micro/benchmarks.jar org.openjdk.bench.java.security.SSLHandshake

Unpatched:

Benchmark                 (resume)  (tlsVersion)   Mode  Cnt      Score     Error  Units
SSLHandshake.doHandshake      true       TLSv1.2  thrpt   15  12608.259 ± 243.496  ops/s
SSLHandshake.doHandshake      true           TLS  thrpt   15   1080.235 ±  18.173  ops/s
SSLHandshake.doHandshake     false       TLSv1.2  thrpt   15    773.913 ±   3.890  ops/s
SSLHandshake.doHandshake     false           TLS  thrpt   15    664.086 ±   5.115  ops/s

Patched:

Benchmark                 (resume)  (tlsVersion)   Mode  Cnt      Score     Error  Units
SSLHandshake.doHandshake      true       TLSv1.2  thrpt   15  12452.246 ± 388.311  ops/s
SSLHandshake.doHandshake      true           TLS  thrpt   15    886.533 ±  30.492  ops/s
SSLHandshake.doHandshake     false       TLSv1.2  thrpt   15    756.435 ±  24.509  ops/s
SSLHandshake.doHandshake     false           TLS  thrpt   15    545.188 ±  12.058  ops/s

Files:

linux-x64-old-benchmark-test-before.log
linux-x64-old-benchmark-test-after.log

./build/*/images/jdk/bin/java -jar build/*/images/test/micro/benchmarks.jar org.openjdk.bench.javax.crypto.full.KEMBench

Unpatched:

Benchmark             (algorithm)  (provider)   Mode  Cnt      Score     Error  Units
KEMBench.decapsulate   ML-KEM-512              thrpt   40  43571.920 ± 114.969  ops/s
KEMBench.decapsulate   ML-KEM-768              thrpt   40  27119.445 ±  81.027  ops/s
KEMBench.decapsulate  ML-KEM-1024              thrpt   40  17741.721 ±  65.516  ops/s
KEMBench.encapsulate   ML-KEM-512              thrpt   40  56625.985 ± 166.244  ops/s
KEMBench.encapsulate   ML-KEM-768              thrpt   40  34092.060 ± 134.979  ops/s
KEMBench.encapsulate  ML-KEM-1024              thrpt   40  22087.044 ±  76.312  ops/s

Patched:

Benchmark             (algorithm)  (provider)   Mode  Cnt      Score     Error  Units
KEMBench.decapsulate   ML-KEM-512              thrpt   40  43159.008 ± 227.063  ops/s
KEMBench.decapsulate   ML-KEM-768              thrpt   40  26732.671 ±  99.653  ops/s
KEMBench.decapsulate  ML-KEM-1024              thrpt   40  17638.713 ± 116.464  ops/s
KEMBench.encapsulate   ML-KEM-512              thrpt   40  56290.042 ± 141.988  ops/s
KEMBench.encapsulate   ML-KEM-768              thrpt   40  33758.707 ± 145.931  ops/s
KEMBench.encapsulate  ML-KEM-1024              thrpt   40  21835.208 ±  88.887  ops/s

Files:

linux-x64-old-benchmark-2-test-before.log
linux-x64-old-benchmark-2-test-after.log

./build/*/images/jdk/bin/java -jar build/*/images/test/micro/benchmarks.jar org.openjdk.bench.javax.crypto.full.KeyPairGeneratorBench
Unpatched:

Benchmark                                          (algorithm)  (keyLength)  (provider)   Mode  Cnt      Score     Error  Units
KeyPairGeneratorBench.EC.generateKeyPair                    EC          256              thrpt   40   9579.384 ±  31.903  ops/s
KeyPairGeneratorBench.EC.generateKeyPair                    EC          384              thrpt   40   1025.890 ±   2.547  ops/s
KeyPairGeneratorBench.EC.generateKeyPair                    EC          521              thrpt   40    551.025 ±   1.614  ops/s
KeyPairGeneratorBench.EdDSA.generateKeyPair              EdDSA          255              thrpt   40   3381.089 ±   9.339  ops/s
KeyPairGeneratorBench.EdDSA.generateKeyPair              EdDSA          448              thrpt   40    970.948 ±   2.494  ops/s
KeyPairGeneratorBench.MLDSA.generateKeyPair          ML-DSA-44            0              thrpt   40  14945.414 ±  38.920  ops/s
KeyPairGeneratorBench.MLDSA.generateKeyPair          ML-DSA-65            0              thrpt   40   7332.506 ±  42.262  ops/s
KeyPairGeneratorBench.MLDSA.generateKeyPair          ML-DSA-87            0              thrpt   40   5349.250 ±  25.104  ops/s
KeyPairGeneratorBench.MLKEM.generateKeyPair         ML-KEM-512            0              thrpt   40  58347.196 ± 138.932  ops/s
KeyPairGeneratorBench.MLKEM.generateKeyPair         ML-KEM-768            0              thrpt   40  36467.284 ±  67.883  ops/s
KeyPairGeneratorBench.MLKEM.generateKeyPair        ML-KEM-1024            0              thrpt   40  23248.778 ±  43.176  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         1024              thrpt   40     90.128 ±   1.918  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         2048              thrpt   40     11.861 ±   0.719  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         3072              thrpt   40      2.982 ±   0.345  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         4096              thrpt   40      1.132 ±   0.227  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         1024              thrpt   40     89.881 ±   3.893  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         2048              thrpt   40     11.322 ±   0.743  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         3072              thrpt   40      2.920 ±   0.393  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         4096              thrpt   40      1.104 ±   0.249  ops/s
KeyPairGeneratorBench.XDH.generateKeyPair                  XDH          255              thrpt   40   6846.240 ±  18.209  ops/s
KeyPairGeneratorBench.XDH.generateKeyPair                  XDH          448              thrpt   40   2015.337 ±   8.035  ops/s
KeyPairGeneratorBench.generateKeyPair                      DSA         1024              thrpt   40  12959.403 ±  65.957  ops/s
KeyPairGeneratorBench.generateKeyPair                      DSA         2048              thrpt   40   2834.255 ±   9.522  ops/s
KeyPairGeneratorBench.generateKeyPair            DiffieHellman         1024              thrpt   40  13673.955 ± 240.552  ops/s
KeyPairGeneratorBench.generateKeyPair            DiffieHellman         2048              thrpt   40   2884.448 ±  69.353  ops/s

Patched:

Benchmark                                          (algorithm)  (keyLength)  (provider)   Mode  Cnt      Score    Error  Units
KeyPairGeneratorBench.EC.generateKeyPair                    EC          256              thrpt   40   9557.561 ± 16.531  ops/s
KeyPairGeneratorBench.EC.generateKeyPair                    EC          384              thrpt   40   1027.535 ±  1.871  ops/s
KeyPairGeneratorBench.EC.generateKeyPair                    EC          521              thrpt   40    549.844 ±  1.828  ops/s
KeyPairGeneratorBench.EdDSA.generateKeyPair              EdDSA          255              thrpt   40   3381.189 ±  5.965  ops/s
KeyPairGeneratorBench.EdDSA.generateKeyPair              EdDSA          448              thrpt   40    972.829 ±  1.566  ops/s
KeyPairGeneratorBench.MLDSA.generateKeyPair          ML-DSA-44            0              thrpt   40  14859.972 ± 56.818  ops/s
KeyPairGeneratorBench.MLDSA.generateKeyPair          ML-DSA-65            0              thrpt   40   7390.224 ± 56.628  ops/s
KeyPairGeneratorBench.MLDSA.generateKeyPair          ML-DSA-87            0              thrpt   40   5341.787 ± 18.094  ops/s
KeyPairGeneratorBench.MLKEM.generateKeyPair         ML-KEM-512            0              thrpt   40  58134.486 ± 98.875  ops/s
KeyPairGeneratorBench.MLKEM.generateKeyPair         ML-KEM-768            0              thrpt   40  36294.342 ± 61.473  ops/s
KeyPairGeneratorBench.MLKEM.generateKeyPair        ML-KEM-1024            0              thrpt   40  22998.948 ± 45.111  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         1024              thrpt   40     91.314 ±  3.391  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         2048              thrpt   40     11.671 ±  0.692  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         3072              thrpt   40      2.890 ±  0.414  ops/s
KeyPairGeneratorBench.RSA.generateKeyPair                  RSA         4096              thrpt   40      1.035 ±  0.265  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         1024              thrpt   40     91.396 ±  2.176  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         2048              thrpt   40     11.590 ±  0.619  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         3072              thrpt   40      2.852 ±  0.379  ops/s
KeyPairGeneratorBench.RSASSAPSS.generateKeyPair     RSASSA-PSS         4096              thrpt   40      1.142 ±  0.236  ops/s
KeyPairGeneratorBench.XDH.generateKeyPair                  XDH          255              thrpt   40   6867.042 ± 29.709  ops/s
KeyPairGeneratorBench.XDH.generateKeyPair                  XDH          448              thrpt   40   2022.844 ±  5.932  ops/s
KeyPairGeneratorBench.generateKeyPair                      DSA         1024              thrpt   40  13039.729 ± 65.189  ops/s
KeyPairGeneratorBench.generateKeyPair                      DSA         2048              thrpt   40   2837.620 ±  4.555  ops/s
KeyPairGeneratorBench.generateKeyPair            DiffieHellman         1024              thrpt   40  13754.062 ± 34.411  ops/s
KeyPairGeneratorBench.generateKeyPair            DiffieHellman         2048              thrpt   40   2917.658 ±  3.999  ops/s

Files:

linux-x64-old-benchmark-3-test-before.log
linux-x64-old-benchmark-3-test-after.log

@rm-gh-8

rm-gh-8 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Analysis:

  1. SSLHandshake: Roughly ~18% regression on TLSv1.3 handshakes and TLSv1.2 is unaffected.
  2. KEMBench: Small regression (up to roughly 1.4%) across all KEM operations.
  3. KeyPairGeneratorBench: Similar results.

@simonis

simonis commented Jul 16, 2026

Copy link
Copy Markdown
Member

Thanks for the benchmark comparison. I'm a little concerned with the 18% regression in TLS1.3 handshakes.

I think we should ask Oracle if they can confirm the regression and if they see a chance to fix it. I've done so on the original issue: https://bugs.openjdk.org/browse/JDK-8314323

@jerboaa jerboaa 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.

My interop testing of this passed. The patch looks good to me.

@simonis simonis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It looks like the increased handshake time is the price we have to pay for additional security (see more details in the discussion on the JBS issue: https://bugs.openjdk.org/browse/JDK-8314323).

@rm-gh-8 , please make sure we mention this backport prominently in our release notes and specifically call out the regression for the TLS handshake and how it can be worked around by changing the order of the supported key exchange schemes programatically or with the help of the jdk.tls.namedGroups system property linking to the appropriate section of JEP 527 and the Customizing the Supported Named Groups for TLS/DTLS Key Exchange section of the "Java Secure Socket Extension (JSSE) Reference Guide".

@rm-gh-8

rm-gh-8 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Sounds good Volker.

@rm-gh-8

rm-gh-8 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

/approval request for backport of JDK-8314323: Implement JEP 527: TLS 1.3 Hybrid Key Exchange.

This PR adds ML-KEM and hybrid post-quantum key exchange support to the JSSE provider.

For parity with Oracle JDK.

High risk - This is a security critical change that can potentially cause breaking interoperability with other TLS stacks and regressions to existing ECDHE/FFDHE handshakes

@openjdk

openjdk Bot commented Jul 21, 2026

Copy link
Copy Markdown

@rm-gh-8
8314323: The approval request has been created successfully.

@openjdk openjdk Bot added the approval Requires approval; will be removed when approval is received label Jul 21, 2026
@gnu-andrew

Copy link
Copy Markdown
Member

@rm-gh-8 , please make sure we mention this backport prominently in our release notes and specifically call out the regression for the TLS handshake and how it can be worked around by changing the order of the supported key exchange schemes programatically or with the help of the jdk.tls.namedGroups system property linking to the appropriate section of JEP 527 and the Customizing the Supported Named Groups for TLS/DTLS Key Exchange section of the "Java Secure Socket Extension (JSSE) Reference Guide".

There is a related release note - https://bugs.openjdk.org/browse/JDK-8377391 - so you should pick that up as a reminder if your tooling tracks those. We do for the upstream project.

Regarding the regression, I think the discussion on the ticket resolves most of the worries.

@openjdk openjdk Bot added ready Pull request is ready to be integrated and removed approval Requires approval; will be removed when approval is received labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport Port of a pull request already in a different code base ready Pull request is ready to be integrated rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

5 participants