#ifndef __STDC_WANT_LIB_EXT1__ #define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface. #endif #include <string.h> #ifdef _WIN32 #include <windows.h> #endif #ifdef __unix__ #include <strings.h> #include <sys/param.h> #endif // C11's bounds-checking interface. #if defined(__STDC_LIB_EXT1__) #define HAVE_MEMSET_S 1 #endif // GNU C Library version 2.25 or later. #if defined(__GLIBC__) && \ (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) #define HAVE_EXPLICIT_BZERO 1 #endif // Newlib #if defined(__NEWLIB__) #define HAVE_EXPLICIT_BZERO 1 #endif // FreeBSD version 11.0 or later. #if defined(__FreeBSD__) && __FreeBSD_version >= 1100037 #define HAVE_EXPLICIT_BZERO 1 #endif // OpenBSD version 5.5 or later. #if defined(__OpenBSD__) && OpenBSD >= 201405 #define HAVE_EXPLICIT_BZERO 1 #endif // NetBSD version 7.2 or later. #if defined(__NetBSD__) && __NetBSD_Version__ >= 702000000 #define HAVE_EXPLICIT_MEMSET 1 #endif // Adapted from // https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130 void memzero(void *const pnt, const size_t len) { #ifdef _WIN32 SecureZeroMemory(pnt, len); #elif defined(HAVE_MEMSET_S) memset_s(pnt, (rsize_t)len, 0, (rsize_t)len); #elif defined(HAVE_EXPLICIT_BZERO) explicit_bzero(pnt, len); #elif defined(HAVE_EXPLICIT_MEMSET) explicit_memset(pnt, 0, len); #else volatile unsigned char *volatile pnt_ = (volatile unsigned char *volatile)pnt; size_t i = (size_t)0U; while (i < len) { pnt_[i++] = 0U; } #endif // explicitly mark the memory as overwritten for the Clang MemorySanitizer // this is only included at compile time if MemorySanitizer is enabled and // should not come with any downsides during regular builds #if defined(__has_feature) #if __has_feature(memory_sanitizer) memset(pnt, 0, len); #endif #endif }