Skip to content

Refactor: Simplify base functionality of Hybrid KEMs#5715

Open
reneme wants to merge 7 commits into
randombit:masterfrom
reneme:rene/restructure_hybrid_kem
Open

Refactor: Simplify base functionality of Hybrid KEMs#5715
reneme wants to merge 7 commits into
randombit:masterfrom
reneme:rene/restructure_hybrid_kem

Conversation

@reneme

@reneme reneme commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

As promised, this is a rework of the Hybrid KEM foundation that we already support in the library. The patch is rather large, but it is mostly moving stuff around and simplifying things as described below.

Before, the base class in the hybrid_kem module allowed for hybridization of an arbitrary number of algorithms (n>=2). This introduced unnecessary complexity given that it is pretty unlikely that we'll see general-purpose hybridization of more than two algorithms any time soon.

Additionally, this lifts the KeyExchange-to-KeyEncapsulation adapter from the concrete TLS 1.3 hybridization implementation into the base class so that it may be reused by other concrete hybridization implementations. Most notably by draft-ietf-lamps-pq-composite-kem (see #5686). For that use case, the Hybrid KEM base class has to be publish as a public API so that the public ML-KEM-Composite classes can inherit from it.

The basic architecture is as follows:

  • KEX_to_KEM_Adapter_PublicKey / KEX_to_KEM_Adapter_PrivateKey (in the kex_to_kem_adapter module)
    These classes take ownership of a Key-Exchange keypair (i.e. DH, ECDH or X25519/X448) and build a canonical Key-Encapsulation API on their basic functionality. Essentially "KeyGen -> KeyGen", "Encaps -> KeyGen + Agree", "Decaps -> Agree". This module existed before and is essentially unchanged in this patch.
  • Hybrid_KEM_PublicKey / Hybrid_KEM_PrivateKey (in the hybrid_kem module)
    These abstract classes now take exactly two keypairs (of either KEX or KEM algorithms) and implement the low-level mechanics to provide a hybrid KEM. Concrete hybridization implementations can use them as base classes and modify the combination specifics as needed. Most notably, key serialization, algorithm identification and shared secret combination.
  • Hybrid_TLS_KEM_PublicKey / Hybrid_TLS_KEM_PrivateKey (in the tls13_pqc module)
    Those implement the concrete TLS 1.3 PQ-hybrid as specified in draft-ietf-tls-hybrid-design. They are concrete subclasses of Hybrid_KEM_PublicKey / Hybrid_KEM_PrivateKey.

@reneme
reneme requested a review from Copilot July 7, 2026 07:34
@reneme reneme self-assigned this Jul 7, 2026

Copilot AI 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.

Pull request overview

This PR refactors Botan’s hybrid KEM foundation to assume exactly two component algorithms (instead of N≥2), and lifts the KEX→KEM adapter usage into the hybrid_kem base so multiple hybrid implementations (e.g., TLS and future composites) can reuse it.

Changes:

  • Refactor hybrid_kem base keys/ops to operate on std::pair-based key storage (PairOfPublicKeys / PairOfPrivateKeys) and corresponding paired ciphertext/shared-secret handling.
  • Update the TLS 1.3 PQ-hybrid key implementation to the new two-key hybrid foundation and rename TLS-specific key types (Hybrid_TLS_KEM_*).
  • Adjust tests and module dependency declarations to match the new architecture (and remove the now-unused stl_util.h::reduce helper).

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/tests/test_tls_hybrid_kem_key.cpp Updates TLS hybrid KEM tests to the new two-key API and renamed TLS hybrid key types.
src/lib/utils/stl_util.h Removes the internal reduce helper previously used by the N-key hybrid implementation.
src/lib/tls/tls13_pqc/info.txt Updates module dependencies after moving KEX→KEM adapter usage into hybrid_kem.
src/lib/tls/tls13_pqc/hybrid_public_key.h Renames TLS hybrid key classes and adapts interfaces to pair-based hybrid keys.
src/lib/tls/tls13_pqc/hybrid_public_key.cpp Refactors TLS hybrid key parsing/generation/ops wiring to the new two-key base and paired ops types.
src/lib/tls/tls_callbacks.cpp Switches TLS callbacks to use the renamed TLS hybrid KEM key classes.
src/lib/pubkey/hybrid_kem/info.txt Declares kex_to_kem_adapter as a required dependency for the refactored hybrid KEM base.
src/lib/pubkey/hybrid_kem/hybrid_kem.h Refactors hybrid KEM base key abstractions to take exactly two keys via std::pair.
src/lib/pubkey/hybrid_kem/hybrid_kem.cpp Implements pair-based hybrid key construction, auto-wrapping KEX keys into KEX→KEM adapters.
src/lib/pubkey/hybrid_kem/hybrid_kem_ops.h Refactors hybrid KEM combiner ops interfaces to pair-based ciphertext/shared-secret handling.
src/lib/pubkey/hybrid_kem/hybrid_kem_ops.cpp Implements the pair-based encryption/decryption combiner scaffolding.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/lib/pubkey/hybrid_kem/hybrid_kem.h Outdated
Comment thread src/lib/pubkey/hybrid_kem/hybrid_kem.h Outdated
Comment thread src/tests/test_tls_hybrid_kem_key.cpp Outdated
Comment thread src/lib/tls/tls13_pqc/hybrid_public_key.h Outdated
Comment thread src/lib/tls/tls13_pqc/hybrid_public_key.h Outdated
@reneme
reneme force-pushed the rene/restructure_hybrid_kem branch from b61079c to 242d961 Compare July 8, 2026 14:03
@reneme
reneme marked this pull request as ready for review July 8, 2026 14:14
@atreiber94
atreiber94 requested a review from Copilot July 8, 2026 14:16

Copilot AI 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.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.

Comment thread src/tests/test_tls_hybrid_kem_key.cpp
Comment thread src/lib/pubkey/hybrid_kem/hybrid_kem_ops.h
Comment thread src/lib/tls/tls13_pqc/tls_hybrid_kem.cpp Outdated
Comment thread src/lib/tls/tls13_pqc/tls_hybrid_kem.cpp Outdated
Comment thread src/lib/tls/tls13_pqc/tls_hybrid_kem.cpp
Comment thread src/lib/tls/tls13_pqc/tls_hybrid_kem.cpp
reneme added 7 commits July 8, 2026 20:15
Before, the implementation allowed for hybridization of an arbitrary number of
algorithms (n>=2). This introduced unnecessary complexity given that is pretty
unlikely that we'll see general-purpose hybridization of more than two algorithms.

Additionally, this lifts the KeyExchange-to-KeyEncapsulation adapter from the
concrete TLS 1.3 hybridization implementation into the base class so that it
may be reused by other concrete hybridization implementations. Most notably by
draft-ietf-lamps-pq-composite-kem.
Before, the Hybrid_KEM_PublicKey contained an unfortunate default c'tor
that would be silently called in the most-derived class to initialize
the class in a diamond-shape virtual inhertance relationship. This resulted
in unexpected internal states of the public key portion of the object.

Instead, by removing the default c'tor, we now force a more verbose but
easier to understand workaround on the user.
This lets user explicitly unwrap the wrapped KEX-key as necessary.
For TLS 1.3 it is currently just an implementation detail. But for the
Composite ML-KEM implementation it will have to become accessible via the
public API.
The old name 'hybrid_public_key.h' was too generic and might
become ambiguouos in the future.
@reneme
reneme force-pushed the rene/restructure_hybrid_kem branch from 8a8e0c2 to 547378b Compare July 8, 2026 14:46

@falko-strenzke falko-strenzke left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is only a superficial review. The reason is that I don't really see a clearly convincing value in the hybrid_kem and hybrid_kem_ops. Most of the functions they implemenent are one-liners and thus hardly save much code in the derived classes. They make one assumption that may not always hold, namely that the artifacts are concatenated. As a downside they create a lot of interdependency for trivial things. Of course, on the plus side, they add some functions to the child classes that ideally do what is needed.

Regarding this PR, I am not convinced that restricting the number of component schemes to 2 is good idea. I agree that we will probably not see standardization of multi-algorithm combinations beyond 2 component schemes. However, custom algorithm-combinations might in my view choose to combine more than 2.

@reneme

reneme commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

I concur that this base class doesn't provide an awful lot of shared code. However, I think there's value in the standardized approach towards hybrid keys.

Regarding the serialization assumptions: those don't have to be used and can be overridden in concrete subclasses.

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