src: add curlx_memzero() to clear buffers securely

To safely zero memory, introduce `curlx_memzero()`, and map it to
`memset_s()` (C11) or `memset_explicit()` (C23) if auto-detected, or
`explicit_bzero()` or `explicit_memset()` for platforms opted-in, or
fall back to a local workaround if all unavailable. On Windows, always
use `SecureZeroMemory()`, or `SecureZeroMemory2()` with Visual Studio
and Windows SDK 10.0.26100.0+.

Details above are experimental and may change if they cause issues.

Also add macros/functions that zero memory before freeing a buffer:
- `curlx_safefreezero()`: for buffers with size.
- `curlx_safefreezeroz()`: for null-terminated buffers.
- `curlx_freezero()`: for buffers with size.
- `curlx_freezeroz()`: for null-terminated buffers.

`curlx_memzero()` must not be passed a NULL pointer because in some
implementations it is undefined behavior.

Also:
- curl_sha512_256: Replace hard-wired `explicit_memset()` call with new
  `curlx_memzero()`.

Refs:
https://en.cppreference.com/c/string/byte/memset
https://man7.org/linux/man-pages/man3/explicit_bzero.3.html
https://man.freebsd.org/cgi/man.cgi?query=explicit_bzero
https://man.netbsd.org/NetBSD-7.2/explicit_memset.3
https://learn.microsoft.com/previous-versions/windows/desktop/legacy/aa366877(v=vs.85)
https://learn.microsoft.com/windows/win32/memory/winbase-securezeromemory2
https://learn.microsoft.com/cpp/overview/compiler-versions
https://learn.microsoft.com/windows/apps/windows-sdk/downloads
https://jtsoya539.github.io/windows-sdk-versions/

Credits-to: Daniel Gustafsson
Credits-to: Will Cosgrove and co-authors in libssh2
Ref: #13589 (original attempt)
Ref: #21588

Closes #21598
This commit is contained in:
Viktor Szakats 2026-05-13 18:20:33 +02:00
parent 831a151484
commit 066478f634
No known key found for this signature in database
10 changed files with 195 additions and 9 deletions

View file

@ -65,6 +65,16 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
set(HAVE_EVENTFD 1)
endif()
if(ANDROID AND ANDROID_PLATFORM_LEVEL GREATER_EQUAL 34)
set(HAVE_MEMSET_EXPLICIT 1)
endif()
if((APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER_EQUAL 10.9) OR
CMAKE_SYSTEM_NAME STREQUAL "DragonFlyBSD" OR # v6+
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") # v11.2+
set(HAVE_MEMSET_S 1)
elseif(NOT APPLE)
set(HAVE_MEMSET_S 0)
endif()
set(HAVE_FCNTL 1)
set(HAVE_FCNTL_H 1)
set(HAVE_FCNTL_O_NONBLOCK 1)