A security-first C11 implementation of the LCH-KEM hybrid post-quantum KEM combiner.
LCH-KEM C implements the protocol layer that combines ML-KEM and HQC into one fixed-size hybrid KEM output. The design goal is assumption diversity: the final shared secret is derived from both component shared secrets, both ciphertexts, both public keys, the selected suite label, and optional outer transcript context.
This repository is a v1.0.0-rc.1 release candidate. The combiner, framing, cached-key mode, explicit key confirmation, OpenSSL SHAKE256 adapter, optional liboqs adapter, deterministic tests, parser fuzz harness, and smoke benchmark are present. The component KEMs remain external backends by design; this project does not implement ML-KEM or HQC internals.
Read docs/ARCHITECTURE.md for the protocol layout and docs/BUILDING.md for backend, test, fuzzing, and benchmark workflows.
| Layer | Suite 128 | Suite 192 | Suite 256 | Role |
|---|---|---|---|---|
| L | ML-KEM-512 | ML-KEM-768 | ML-KEM-1024 | Module-LWE KEM component |
| C | HQC-128 | HQC-192 | HQC-256 | QC-syndrome-decoding KEM component |
| Combiner | SHAKE256-32 | SHAKE256-32 | SHAKE256-32 | Binds secrets, ciphertexts, public keys, suite, and context |
| Path | Role |
|---|---|
include/lch_kem.h |
Public API, suite constants, object formats, backend ABI |
src/lch_kem.c |
Backend-agnostic LCH-KEM combiner implementation |
src/lch_kem_openssl.c |
SHAKE256 adapter using OpenSSL EVP XOF |
src/lch_kem_oqs.c |
Optional liboqs component KEM backend adapter |
tests/ |
Deterministic fake backend and regression tests |
examples/ |
Minimal API usage example |
fuzz/ |
Public parser fuzz harness |
bench/ |
Smoke benchmark for API overhead only |
The sender parses the hybrid public key into pk_L || pk_C, runs both component encapsulations with independent component randomness, and derives the final 32-byte secret with SHAKE256 over ss_L || ss_C || ct_L || ct_C || pk_L || pk_C || suite_label || context_binding. The recipient parses the stored hybrid secret key, decapsulates both component ciphertexts, and runs the same combiner. The top-level code does not inspect component validity; implicit rejection belongs inside the component backends.
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failureOpenSSL support is enabled by default for SHAKE256. liboqs support is optional and requires an installed liboqs build with ML-KEM and HQC enabled.
cmake -S . -B build \
-DLCH_KEM_WITH_LIBOQS=ON \
-DCMAKE_PREFIX_PATH=/path/to/liboqs/install
cmake --build build
ctest --test-dir build --output-on-failureSee docs/BUILDING.md for CMake options, sanitizer builds, fuzzing, and backend validation.
LCH-KEM C is not an authentication protocol. Identity authentication, downgrade protection, replay protection, cached-key policy, public-key authentication, and transcript integrity must be provided by the outer protocol.
A production deployment must use audited constant-time ML-KEM and HQC backends, run official known-answer tests for the selected backend versions, and validate invalid-ciphertext behavior so component failures are not exposed through the combiner API.
Licensed under the MIT License (see LICENSE).