From f3f97110f6444f94e076222974e29ef86cd4bfbf Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Wed, 28 Oct 2020 14:40:13 +0100 Subject: [PATCH] Automatically perform initialization when slunkcrypt_random_bytes() is called for the first time. --- Makefile | 4 + frontend/src/main.c | 11 +- libslunkcrypt/include/slunkcrypt.h | 11 +- libslunkcrypt/src/junk.c | 206 ++++++++++++++--------------- libslunkcrypt/src/slunkcrypt.c | 2 +- 5 files changed, 113 insertions(+), 121 deletions(-) diff --git a/Makefile b/Makefile index a42ba83..9332f7b 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,10 @@ else SUFFIX := endif +ifeq ($(filter %-mingw32 %-windows-gnu,$(MACHINE)),) + LDFLGS += -lpthread +endif + ifeq ($(STATIC),1) LDFLGS += -static endif diff --git a/frontend/src/main.c b/frontend/src/main.c index 037c2e7..bef3510 100644 --- a/frontend/src/main.c +++ b/frontend/src/main.c @@ -192,7 +192,7 @@ static int encrypt(const char* const passphrase, const CHR* const input_path, co uint64_t nonce; if (slunkcrypt_generate_nonce(&nonce) != SLUNKCRYPT_SUCCESS) { - FPUTS(T("\n\nSlunkCrypt error: Failed to generate salt!\n\n"), stderr); + FPUTS(T("\n\nSlunkCrypt error: Failed to generate nonce!\n\n"), stderr); goto clean_up; } @@ -206,7 +206,7 @@ static int encrypt(const char* const passphrase, const CHR* const input_path, co nonce = swap_bytes_u64(nonce); if (fwrite(&nonce, sizeof(uint64_t), 1U, file_out) < 1U) { - FPUTS(T("\n\nI/O error: Failed to write salt value!\n\n"), stderr); + FPUTS(T("\n\nI/O error: Failed to write nonce value!\n\n"), stderr); goto clean_up; } @@ -338,7 +338,7 @@ static int decrypt(const char* const passphrase, const CHR* const input_path, co uint64_t nonce; if (fread(&nonce, sizeof(uint64_t), 1U, file_in) < 1U) { - FPUTS(T("\n\nI/O error: Failed to read salt value!\n\n"), stderr); + FPUTS(T("\n\nI/O error: Failed to read nonce value!\n\n"), stderr); goto clean_up; } @@ -470,7 +470,7 @@ static int run_test_case(const char *const message, const uint64_t checksum) uint64_t nonce; if (slunkcrypt_generate_nonce(&nonce) != SLUNKCRYPT_SUCCESS) { - FPUTS(T("\n\nWhoops: Failed to generate salt!\n\n"), stderr); + FPUTS(T("\n\nWhoops: Failed to generate nonce!\n\n"), stderr); return EXIT_FAILURE; } @@ -596,8 +596,6 @@ int MAIN(const int argc, CHR *const argv[]) FPRINTF(stderr, T("SlunkCrypt Utility (%") T(PRIstr) T("-%") T(PRIstr) T("), by LoRd_MuldeR \n"), OS_TYPE, CPU_ARCH); FPRINTF(stderr, T("Using libSlunkCrypt v%u.%u.%u [%") T(PRIstr) T("]\n\n"), SLUNKCRYPT_VERSION_MAJOR, SLUNKCRYPT_VERSION_MINOR, SLUNKCRYPT_VERSION_PATCH, SLUNKCRYPT_BUILD); - slunkcrypt_startup(); - /* ----------------------------------------------------- */ /* Parse arguments */ /* ----------------------------------------------------- */ @@ -714,7 +712,6 @@ clean_up: free(passphrase_buffer); } - slunkcrypt_cleanup(); return result; } diff --git a/libslunkcrypt/include/slunkcrypt.h b/libslunkcrypt/include/slunkcrypt.h index 8ec5694..30546f0 100644 --- a/libslunkcrypt/include/slunkcrypt.h +++ b/libslunkcrypt/include/slunkcrypt.h @@ -78,13 +78,7 @@ SLUNKCRYPT_API extern const char *const SLUNKCRYPT_BUILD; SLUNKCRYPT_API extern volatile int g_slunkcrypt_abort_flag; /* - * Global (de)initialization routines - */ -SLUNKCRYPT_API void slunkcrypt_startup(void); -SLUNKCRYPT_API void slunkcrypt_cleanup(void); - -/* - * Seed generator + * Nonce generator */ SLUNKCRYPT_API int slunkcrypt_generate_nonce(uint64_t* const nonce); @@ -110,10 +104,11 @@ SLUNKCRYPT_API int slunkcrypt_decrypt_inplace(const slunkcrypt_t context, uint8_ /* * Auxiliary functions */ -SLUNKCRYPT_API int slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length); +SLUNKCRYPT_API size_t slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length); SLUNKCRYPT_API void slunkcrypt_bzero(void* const ptr, const size_t length); #ifdef __cplusplus } #endif #endif + diff --git a/libslunkcrypt/src/junk.c b/libslunkcrypt/src/junk.c index 8321b28..98a4f1b 100644 --- a/libslunkcrypt/src/junk.c +++ b/libslunkcrypt/src/junk.c @@ -15,159 +15,155 @@ #ifdef _WIN32 # define WIN32_LEAN_AND_MEAN 1 # include -# define SCHED_YIELD() Sleep(1U) -# define COMPARE_AND_SWAP(PTR,OLD,NEW) InterlockedCompareExchange((PTR),(NEW),(OLD)) -# define ATOMIC_STORE(PTR,VAL) InterlockedExchange((PTR),(VAL)) -# if defined(SecureZeroMemory) -# define HAVE_SECURE_ZERO_MEMORY 1 -# else -# define HAVE_SECURE_ZERO_MEMORY 0 -# endif -# define HAVE_GETRANDOM 0 -# define HAVE_EXPLICIT_BZERO 0 #else # include -# include -# define SCHED_YIELD() sched_yield() -# if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) -# define COMPARE_AND_SWAP(PTR,OLD,NEW) __sync_val_compare_and_swap((PTR),(OLD),(NEW)) -# define ATOMIC_STORE(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELEASE) -# else -# define COMPARE_AND_SWAP(PTR,OLD,NEW) ((OLD)) -# define ATOMIC_STORE(PTR,VAL) do { *(PTR) = (VAL); } while(0) -# endif -# if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) -# define HAVE_GETRANDOM 1 -# define HAVE_EXPLICIT_BZERO 1 -# elif defined(__FreeBSD__) && (__FreeBSD__ >= 12) -# define HAVE_GETRANDOM 1 -# define HAVE_EXPLICIT_BZERO 1 -# elif defined(__FreeBSD__) && (__FreeBSD__ >= 11) -# define HAVE_GETRANDOM 0 -# define HAVE_EXPLICIT_BZERO 1 -# else -# define HAVE_GETRANDOM 0 -# define HAVE_EXPLICIT_BZERO 0 -# endif -# if HAVE_GETRANDOM -# include -# endif +# include #endif // ========================================================================== -// Critical sections +// One-time init // ========================================================================== -static int enter_critsec(volatile long *const lock, const int flag) +#ifdef _WIN32 +# define ONCE_TYPE volatile LONG +# define ONCE_INIT 0L +# define ONCE_FUNC win32_run_once +#else +# define ONCE_TYPE pthread_once_t +# define ONCE_INIT PTHREAD_ONCE_INIT +# define ONCE_FUNC pthread_once +#endif + +#ifdef _WIN32 +static void win32_run_once(ONCE_TYPE *const control, void (*init_routine)(void)) { - const long expected = flag ? 0L : 1L; - long status; - while ((status = COMPARE_AND_SWAP(lock, expected, -1L)) < 0L) + LONG status; + while ((status = InterlockedCompareExchange(control, -1L, 0L)) != 0L) { - SCHED_YIELD(); + if(status > 0L) + { + return; /*already initialized*/ + } + SwitchToThread(); } - return (status == expected); -} - -static void leave_critsec(volatile long *const lock, const int flag) -{ - ATOMIC_STORE(lock, flag ? 1L : 0L); + init_routine(); + InterlockedExchange(control, 1L); } +#endif // ========================================================================== -// (De)Initialization +// Random bytes // ========================================================================== -static volatile long s_initialized = 0L; +#ifdef _WIN32 +# define HAVE_GETRANDOM 0 +#else +# if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) +# define HAVE_GETRANDOM 1 +# elif defined(__FreeBSD__) && (__FreeBSD__ >= 12) +# define HAVE_GETRANDOM 1 +# else +# define HAVE_GETRANDOM 0 +# endif +#endif +#if HAVE_GETRANDOM +# include +#endif +/* Global state */ +static ONCE_TYPE s_random_is_initialized = ONCE_INIT; #if defined(_WIN32) -typedef BOOLEAN(WINAPI *genrandom_t)(void*, ULONG); -static HMODULE s_advapi32 = NULL; -static genrandom_t s_genrandom = NULL; +typedef BOOLEAN(WINAPI *rtl_genrandom_t)(void *buffer, ULONG buff_size); +static HMODULE s_dll_advapi32 = NULL; +static rtl_genrandom_t s_rtl_genrandom = NULL; #elif !HAVE_GETRANDOM static const char *const DEV_RANDOM[] = { "/dev/urandom", "/dev/arandom", "/dev/random", NULL }; static int s_random_fd = -1; #endif -void slunkcrypt_startup(void) +/* Close down CSRNG */ +static void exit_random_source(void) { - if (enter_critsec(&s_initialized, 1)) - { #if defined(_WIN32) - if ((s_advapi32 = LoadLibraryW(L"advapi32.dll"))) - { - s_genrandom = (genrandom_t)GetProcAddress(s_advapi32, "SystemFunction036"); - } -#elif !HAVE_GETRANDOM - for (size_t i = 0U; (s_random_fd < 0) && DEV_RANDOM[i]; ++i) - { - s_random_fd = open(DEV_RANDOM[i], O_RDONLY); - } -#endif - leave_critsec(&s_initialized, 1); + s_rtl_genrandom = NULL; + if (s_dll_advapi32) + { + FreeLibrary(s_dll_advapi32); + s_dll_advapi32 = NULL; } +#elif !HAVE_GETRANDOM + if (s_random_fd >= 0) + { + close(s_random_fd); + s_random_fd = -1; + } +#endif } -void slunkcrypt_cleanup(void) +/* Initialize CSRNG */ +static void init_random_source(void) { - if (enter_critsec(&s_initialized, 0)) - { #if defined(_WIN32) - s_genrandom = NULL; - if (s_advapi32) - { - FreeLibrary(s_advapi32); - s_advapi32 = NULL; - } -#elif !HAVE_GETRANDOM - if (s_random_fd >= 0) - { - close(s_random_fd); - s_random_fd = -1; - } -#endif - leave_critsec(&s_initialized, 0); + if ((s_dll_advapi32 = LoadLibraryW(L"advapi32.dll"))) + { + s_rtl_genrandom = (rtl_genrandom_t)GetProcAddress(s_dll_advapi32, "SystemFunction036"); } +#elif !HAVE_GETRANDOM + for (size_t i = 0U; DEV_RANDOM[i]; ++i) + { + if ((s_random_fd = open(DEV_RANDOM[i], O_RDONLY)) >= 0) + { + break; /*success*/ + } + } +#endif + atexit(exit_random_source); } -// ========================================================================== -// Auxiliary functions -// ========================================================================== - -int slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length) +/* Generate random bytes */ +size_t slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length) { + ONCE_FUNC(&s_random_is_initialized, init_random_source); #if defined(_WIN32) - if ((length <= ((size_t)ULONG_MAX))) + if (s_rtl_genrandom) { - if (s_genrandom) - { - return s_genrandom(buffer, (ULONG)length) ? 0 : (-1); - } + const ULONG buff_size = (ULONG)length; + return s_rtl_genrandom(buffer, buff_size) ? buff_size : 0U; } - return -1; #elif HAVE_GETRANDOM - if (getrandom(buffer, length, 0U) >= length) - { - return 0; - } - return -1; + const ssize_t result = getrandom(buffer, length, 0U); + return (result < 0) ? 0U : ((size_t)result); #else if (s_random_fd >= 0) { - if (read(s_random_fd, buffer, length) >= length) - { - return 0; - } + const ssize_t result = read(s_random_fd, buffer, length); + return (result < 0) ? 0U : ((size_t)result); } - return -1; #endif + return 0U; } +// ========================================================================== +// Zero memory +// ========================================================================== + +#ifdef _WIN32 +# define HAVE_EXPLICIT_BZERO 0 +#else +# if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) +# define HAVE_EXPLICIT_BZERO 1 +# elif defined(__FreeBSD__) && (__FreeBSD__ >= 11) +# define HAVE_EXPLICIT_BZERO 1 +# else +# define HAVE_EXPLICIT_BZERO 0 +# endif +#endif + void slunkcrypt_bzero(void* const ptr, const size_t length) { if ((ptr) && (length > 0U)) { -#if HAVE_SECURE_ZERO_MEMORY +#if defined(_WIN32) && defined(SecureZeroMemory) SecureZeroMemory(ptr, length); #elif HAVE_EXPLICIT_BZERO explicit_bzero(ptr, length); diff --git a/libslunkcrypt/src/slunkcrypt.c b/libslunkcrypt/src/slunkcrypt.c index 59a9feb..9273ac4 100644 --- a/libslunkcrypt/src/slunkcrypt.c +++ b/libslunkcrypt/src/slunkcrypt.c @@ -303,7 +303,7 @@ int slunkcrypt_generate_nonce(uint64_t* const nonce) } do { - if (slunkcrypt_random_bytes((uint8_t*)nonce, sizeof(uint64_t)) != 0) + if (slunkcrypt_random_bytes((uint8_t*)nonce, sizeof(uint64_t)) != sizeof(uint64_t)) { return SLUNKCRYPT_FAILURE; }