[gnutls-devel] GnuTLS | GnuTLS Security Disclosure: Non-Zeroizing Free of Shared Secret Buffers in Hybrid Key Exchange (#1841)

Read-only notification of GnuTLS library development activities gnutls-devel at lists.gnutls.org
Mon Apr 13 09:16:11 CEST 2026



liyue created an issue: https://gitlab.com/gnutls/gnutls/-/work_items/1841



## Description of problem: GnuTLS Security Disclosure: Non-Zeroizing Free of Shared Secret Buffers in Hybrid Key Exchange

## Affected branch: master

We are researchers conducting a systematic security study of hybrid post-quantum KEM implementations across open-source projects. During our analysis of GnuTLS's hybrid key share extension, we identified that shared secret buffers are freed using `_gnutls_free_datum()` instead of the secure `_gnutls_free_key_datum()` in two functions in `lib/ext/key_share.c`.

## Summary

In `server_use_key_share_single()` and `client_use_key_share_single()`, KEM/ECDH shared secrets are stored in a local `gnutls_datum_t key` variable. After the shared secret is copied to `session->key.key` via `append_key_datum()`, the original buffer is freed with `_gnutls_free_datum(&key)`, which calls `gnutls_free()` without first clearing the buffer contents. The secure alternative `_gnutls_free_key_datum(&key)` calls `zeroize_key()` before `gnutls_free()`.

## Affected Code

**Function `server_use_key_share_single()`** — 3 locations:

```c
// Line 464-465 (ECDH P-256/P-384 shared secret)


ret = append_key_datum(&session->key.key, &key);
_gnutls_free_datum(&key);  // should be _gnutls_free_key_datum(&key)

// Line 508-509 (X25519/X448 shared secret)


ret = append_key_datum(&session->key.key, &key);
_gnutls_free_datum(&key);  // should be _gnutls_free_key_datum(&key)

// Line 605-606 (ML-KEM/Kyber shared secret from _gnutls_pk_encaps)


ret = append_key_datum(&session->key.key, &key);
_gnutls_free_datum(&key);  // should be _gnutls_free_key_datum(&key)
```

**Function `client_use_key_share_single()`** — 4 locations:

```c
// Lines 703, 742, 779, 800 — same pattern for ECDH, X25519, DH, ML-KEM


ret = append_key_datum(&session->key.key, &key);
_gnutls_free_datum(&key);  // should be _gnutls_free_key_datum(&key)
```

## The Difference

>From `lib/datum.h`:

```c
// _gnutls_free_datum: does NOT clear buffer contents


inline static void _gnutls_free_datum(gnutls_datum_t *dat) {
    gnutls_free(dat->data);   // free only
    dat->size = 0;
}

// _gnutls_free_key_datum: clears buffer BEFORE freeing


inline static void _gnutls_free_key_datum(gnutls_datum_t *dat) {
    zeroize_key(dat->data, dat->size);  // zero first
    gnutls_free(dat->data);              // then free
    dat->size = 0;
}
```

## Impact

After `_gnutls_free_datum(&key)`, the shared secret bytes remain in freed heap memory until overwritten by a future allocation. In a hybrid key exchange (e.g., `mlkem768nistp256`), both the ECDH and ML-KEM shared secrets are affected. An attacker with memory read access (e.g., via a separate memory disclosure vulnerability, cold boot attack, or core dump) could recover the shared secret from freed heap pages.

We note that this issue also affects non-hybrid key exchanges (pure ECDH, X25519, FFDHE) in the same functions, since the same `_gnutls_free_datum(&key)` pattern is used for all key agreement types.

## Suggested Fix

Replace `_gnutls_free_datum(&key)` with `_gnutls_free_key_datum(&key)` at the 7 identified locations. The secure variant is already available in GnuTLS and is used elsewhere in the codebase for handling sensitive key material.

## Standard Reference

- NIST SP 800-227: "Intermediate values used in any given KEM algorithm SHALL be destroyed before the algorithm terminates"

-- 
Reply to this email directly or view it on GitLab: https://gitlab.com/gnutls/gnutls/-/work_items/1841
You're receiving this email because of your account on gitlab.com. Unsubscribe from this thread: https://gitlab.com/-/sent_notifications/4-bmyu10f248po2yhf3bwnzfcpv-a84t7/unsubscribe | Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gnutls-devel/attachments/20260413/a900e13b/attachment-0001.html>


More information about the Gnutls-devel mailing list