Security › kem-01 · Constant-time review · Performance: x86_1 · arm_1
Aigis-Enc+ (kem-01)
| Candidate | Aigis-Enc+ |
|---|---|
| Family | Lattice (Module-LWE) |
| Archive | Aigis-Enc+.zip (SHA-256: 1c053133175cd189fd9f0e058bde684168f55a6fc3871de2a755404a08990186) |
| Specification | kem-01-spec.pdf PDF |
| Performance | x86_1 · arm_1 |
kem-01-1: Ineffective implicit rejection breaks IND-CCA security
| Severity | Critical |
|---|---|
| Scope | implementation |
| Status | Confirmed |
| Affected | Reference implementation, all three parameter sets |
| Discovery | Trivial |
| Exploitation | Trivial |
| Credit | Markku-Juhani O. Saarinen markku-juhani.saarinen@tuni.fi, with AI assistance |
| Date | 2026-09-21 |
Additional reference: Xiong and Wang, ePrint 2026/2232, 2026-09-28 revision, §7
Changing a ciphertext bit frequently leaves the decapsulated shared secret unchanged. An exhaustive sweep of Aigis-enc1 found that 5,632 of 7,168 single-bit ciphertext changes return the original shared secret. The same defect was reproduced in the other two parameter sets.
mkem_dec writes the candidate valid secret to the output before checking the re-encrypted ciphertext. On failure, the intended constant-time replacement writes into the wrong buffer, leaving the already-returned candidate secret untouched. Rejection is therefore ineffective.
An attacker given a challenge ciphertext and candidate challenge key can modify the ciphertext, decapsulate it through the allowed CCA oracle, and compare the result with the candidate key. Retention identifies the real encapsulated key and provides a direct IND-CCA distinguisher. This violates the claimed IND-CCA security at every submitted level.
Reproducing
Commands below run in a checkout of the ngcc-harness repository with the candidate built (see its README).
Build the candidate and the reproducer, then run:
make -C api harness && make -C tools && make -C kem-01
tools/ngcc_attack kem-ct-flip kem-01/lib/libAigis-enc1.so
tools/reproduce.sh runs this together with the other supported runtime
witnesses and their controls. See tools/README.md.
kem-01-2: Rejection reads a secret before the secret-key object
| Severity | Low |
|---|---|
| Scope | implementation |
| Status | Confirmed |
| Affected | Reference implementation, all three parameter sets |
| Discovery | Trivial |
| Exploitation | Every rejected ciphertext triggers an out-of-bounds read; no disclosure or control-flow impact demonstrated |
| Credit | Markku-Juhani O. Saarinen markku-juhani.saarinen@tuni.fi, with AI assistance |
| Date | 2026-09-21 |
The rejection path reads its fallback secret from sk - SEED_BYTES, before the start of the caller's secret-key object. Key generation stores that value at sk + SK_BYTES - SEED_BYTES. All three submitted kem.c files contain the same pointer error.
This is undefined behavior on every rejected ciphertext. Another assignment error in the submitted decapsulation path prevents the resulting fallback value from replacing the candidate shared secret. Correcting only that assignment would expose this second defect: rejection would derive its output from unrelated memory rather than the secret value stored in the key. The archived behavior is an out-of-bounds read, with no memory disclosure or control-flow impact demonstrated, hence Low.
The implementation must read the final SEED_BYTES of the secret-key object and must validate this repair independently of the separate fallback-selection error.
Reproducing
Commands below run in a checkout of the ngcc-harness repository with the candidate built (see its README).
The defect is directly visible in each reference implementation's kem.c: mkem_dec passes sk - SEED_BYTES to hash_g, while mkem_keygen stores the rejection secret at sk + SK_BYTES - SEED_BYTES.
kem-01-3: The external DRBG is used as a KDF
| Severity | Low |
|---|---|
| Scope | implementation |
| Status | Confirmed |
| Affected | Aigis-Enc+-I, -II and -III ICCS reference implementations |
| Discovery | Trivial |
| Exploitation | Replacing the external RBG changes deterministic matrix expansion and breaks interoperability; the frozen submitted build is internally consistent |
| Credit | Markku-Juhani O. Saarinen markku-juhani.saarinen@tuni.fi, with AI assistance |
| Date | 2026-10-03 |
Under USE_NICCS_API, kdf_init resets an ICCS DRNG_ctx from its input and kdf_squeezeblocks reads the resulting stream (hashkdf.c:91–98). Matrix generation calls this interface from public seeds (gen_a.c:50–63). Thus a nominally external RBG supplies a deterministic KDF whose exact byte stream is part of the algorithm. A different secure RBG need not reproduce it.
The shipped drng.c makes the three implementations work and this is not a cryptanalytic break. The defect is the unstated seed-to-stream dependency; it should be a scheme-defined XOF/KDF.
Reproducing
Commands below run in a checkout of the ngcc-harness repository with the candidate built (see its README).
python3 security/rbg_protocol_dependency.py --report-id kem-01-3