DHKEM decapsulation ignores the supplied receiver-public-key length
Closed, ResolvedPublic

Assigned To
Authored By
werner
Tue, Aug 4, 4:58 PM
Subscribers

Description

DHKEM decapsulation ignores the supplied receiver-public-key length

The public KEM dispatcher validates secret-key, encapsulation, and output sizes for DHKEM25519 and DHKEM448 but does not validate optional_len. It then treats optional as the receiver public key. The lower layer copies a fixed curve-sized value from that pointer, so a non-null short buffer causes an out-of-bounds read.

Vulnerable code

In cipher/kem.c, function _gcry_kem_decap:

if (seckey_len != GCRY_KEM_DHKEM25519_SECKEY_LEN
    || ciphertext_len != GCRY_KEM_DHKEM25519_ENCAPS_LEN
    || shared_len != GCRY_KEM_DHKEM25519_SHARED_LEN)
  return GPG_ERR_INV_ARG;
return _gcry_ecc_dhkem_decap (algo, seckey, ciphertext, shared,
                              optional);

Why it matters

Supplying a one-byte optional buffer is accepted by the dispatcher despite DHKEM's fixed-width receiver-public-key contract; the ASan reproducer observed a fixed 32-byte read beyond that allocation. An exact length check made the reproducer return an error cleanly. An attacker must influence arguments to the direct KEM API; the likely result is a crash, although adjacent readable bytes can also affect the derived secret. No direct memory disclosure was demonstrated.

Proposed fix

For each DHKEM variant, reject (optional && optional_len != PUBKEY_LEN) and (!optional && optional_len != 0) before dispatch, then pass the validated length into the lower layer as defense in depth. Preserve the intentional NULL, 0 mode, which recomputes the receiver public key from the secret key. Add ASan regression tests for null/inconsistent, one-byte-short, exact, and oversized optional buffers for both X25519 and X448, plus known-answer tests for both valid modes.

Related Objects

Event Timeline

werner triaged this task as Normal priority.Tue, Aug 4, 4:58 PM
werner created this task.
werner created this object with visibility "Public (No Login Required)".
werner created this object with edit policy "Contributor (Project)".
werner updated the task description. (Show Details)
gniibe changed the task status from Open to Testing.Wed, Aug 12, 4:53 AM
gniibe mentioned this in Unknown Object (Maniphest Task).Mon, Aug 24, 8:26 AM
werner shifted this object from the Restricted Space space to the S1 Public space.