diff --git a/libslunkcrypt/include/slunkcrypt.h b/libslunkcrypt/include/slunkcrypt.h index 338d1b6..8ec5694 100644 --- a/libslunkcrypt/include/slunkcrypt.h +++ b/libslunkcrypt/include/slunkcrypt.h @@ -86,13 +86,13 @@ SLUNKCRYPT_API void slunkcrypt_cleanup(void); /* * Seed generator */ -SLUNKCRYPT_API int slunkcrypt_generate_salt(uint64_t* const seed); +SLUNKCRYPT_API int slunkcrypt_generate_nonce(uint64_t* const nonce); /* * Allocate, reset or free state */ -SLUNKCRYPT_API slunkcrypt_t slunkcrypt_alloc(const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len); -SLUNKCRYPT_API int slunkcrypt_reset(const slunkcrypt_t context, const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len); +SLUNKCRYPT_API slunkcrypt_t slunkcrypt_alloc(const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len); +SLUNKCRYPT_API int slunkcrypt_reset(const slunkcrypt_t context, const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len); SLUNKCRYPT_API void slunkcrypt_free(const slunkcrypt_t context); /* diff --git a/libslunkcrypt/include/slunkcrypt.hpp b/libslunkcrypt/include/slunkcrypt.hpp index 614f8e2..1971e80 100644 --- a/libslunkcrypt/include/slunkcrypt.hpp +++ b/libslunkcrypt/include/slunkcrypt.hpp @@ -16,11 +16,11 @@ class SlunkCryptEncr public: SlunkCryptEncr(const std::string &passwd) { - if (slunkcrypt_generate_salt(&m_salt) != SLUNKCRYPT_SUCCESS) + if (slunkcrypt_generate_nonce(&m_nonce) != SLUNKCRYPT_SUCCESS) { throw std::runtime_error("Failed to generate the seed value!"); } - if ((m_instance = slunkcrypt_alloc(m_salt, (const uint8_t*)passwd.c_str(), passwd.length())) == SLUNKCRYPT_NULL) + if ((m_instance = slunkcrypt_alloc(m_nonce, (const uint8_t*)passwd.c_str(), passwd.length())) == SLUNKCRYPT_NULL) { throw std::runtime_error("Failed to create encoder instance!"); } @@ -29,7 +29,7 @@ public: SlunkCryptEncr(SlunkCryptEncr &&other) noexcept { this->m_instance = other.m_instance; - this->m_salt = other.m_salt; + this->m_nonce = other.m_nonce; other.m_instance = SLUNKCRYPT_NULL; } @@ -65,24 +65,24 @@ public: return (slunkcrypt_encrypt_inplace(m_instance, buffer.data(), buffer.size()) == SLUNKCRYPT_SUCCESS); } - uint64_t salt_value(void) const + uint64_t get_nonce(void) const { - return m_salt; + return m_nonce; } private: SlunkCryptEncr(const SlunkCryptEncr&); SlunkCryptEncr& operator=(const SlunkCryptEncr&); - uint64_t m_salt; + uint64_t m_nonce; slunkcrypt_t m_instance; }; class SlunkCryptDecr { public: - SlunkCryptDecr(const uint64_t salt, const std::string& passwd) + SlunkCryptDecr(const uint64_t nonce, const std::string& passwd) { - if ((m_instance = slunkcrypt_alloc(salt, (const uint8_t*)passwd.c_str(), passwd.length())) == SLUNKCRYPT_NULL) + if ((m_instance = slunkcrypt_alloc(nonce, (const uint8_t*)passwd.c_str(), passwd.length())) == SLUNKCRYPT_NULL) { throw std::runtime_error("Failed to create encoder instance!"); } diff --git a/libslunkcrypt/src/junk.c b/libslunkcrypt/src/junk.c index 37c8703..8321b28 100644 --- a/libslunkcrypt/src/junk.c +++ b/libslunkcrypt/src/junk.c @@ -3,11 +3,21 @@ /* This work has been released under the CC0 1.0 Universal license! */ /******************************************************************************/ -#include +/* Internal */ +#include "../include/slunkcrypt.h" +/* CRT */ +#include +#include +#include + +/* Platform compatibility */ #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 @@ -17,8 +27,15 @@ # define HAVE_EXPLICIT_BZERO 0 #else # include -# include -# 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 @@ -37,10 +54,32 @@ # endif #endif +// ========================================================================== +// Critical sections +// ========================================================================== + +static int enter_critsec(volatile long *const lock, const int flag) +{ + const long expected = flag ? 0L : 1L; + long status; + while ((status = COMPARE_AND_SWAP(lock, expected, -1L)) < 0L) + { + SCHED_YIELD(); + } + return (status == expected); +} + +static void leave_critsec(volatile long *const lock, const int flag) +{ + ATOMIC_STORE(lock, flag ? 1L : 0L); +} + // ========================================================================== // (De)Initialization // ========================================================================== +static volatile long s_initialized = 0L; + #if defined(_WIN32) typedef BOOLEAN(WINAPI *genrandom_t)(void*, ULONG); static HMODULE s_advapi32 = NULL; @@ -52,35 +91,43 @@ static int s_random_fd = -1; void slunkcrypt_startup(void) { + if (enter_critsec(&s_initialized, 1)) + { #if defined(_WIN32) - if (s_advapi32 || (s_advapi32 = LoadLibraryW(L"advapi32.dll"))) - { - s_genrandom = (genrandom_t)GetProcAddress(s_advapi32, "SystemFunction036"); - } + 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); - } + 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); + } } void slunkcrypt_cleanup(void) { + if (enter_critsec(&s_initialized, 0)) + { #if defined(_WIN32) - s_genrandom = NULL; - if (s_advapi32) - { - FreeLibrary(s_advapi32); - s_advapi32 = NULL; - } + 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; - } + if (s_random_fd >= 0) + { + close(s_random_fd); + s_random_fd = -1; + } #endif + leave_critsec(&s_initialized, 0); + } } // ========================================================================== diff --git a/libslunkcrypt/src/slunkcrypt.c b/libslunkcrypt/src/slunkcrypt.c index 3a19030..59a9feb 100644 --- a/libslunkcrypt/src/slunkcrypt.c +++ b/libslunkcrypt/src/slunkcrypt.c @@ -7,22 +7,25 @@ #define _CRT_RAND_S 1 #endif -#include -#include -#include +/* Internal */ +#include "../include/slunkcrypt.h" #include "version.h" -#ifdef _MSC_VER -#define FORCE_INLINE __forceinline -#define UNUSED __pragma(warning(suppress: 4189)) +/* CRT */ +#include +#include +#include + +/* Compiler compatibility */ +#if defined(_MSC_VER) +# define FORCE_INLINE __forceinline +# define UNUSED __pragma(warning(suppress: 4189)) +#elif defined(__GNUC__) +# define FORCE_INLINE __attribute__((always_inline)) inline +# define UNUSED __attribute__((unused)) #else -#ifdef __GNUC__ -#define FORCE_INLINE __attribute__((always_inline)) inline -#define UNUSED __attribute__((unused)) -#else -#define FORCE_INLINE inline -#define UNUSED -#endif +# define FORCE_INLINE inline +# define UNUSED #endif /* Version info */ @@ -195,7 +198,7 @@ static void random_seed(rand_state_t* const state, const uint64_t salt, const ui slunkcrypt_bzero(&key, sizeof(key_data_t)); for (size_t i = 0U; i < 97U; ++i) { - volatile UNUSED uint32_t u = random_next(state); + UNUSED volatile uint32_t u = random_next(state); } } @@ -203,7 +206,7 @@ static void random_seed(rand_state_t* const state, const uint64_t salt, const ui // Initialization // ========================================================================== -static int initialize_state(crypt_state_t* const crypt_state, const uint64_t salt, const uint8_t* const passwd, const size_t passwd_len) +static int initialize_state(crypt_state_t* const crypt_state, const uint64_t nonce, const uint8_t* const passwd, const size_t passwd_len) { slunkcrypt_bzero(crypt_state, sizeof(crypt_state_t)); @@ -211,7 +214,7 @@ static int initialize_state(crypt_state_t* const crypt_state, const uint64_t sal rand_state_t rand_state; for (size_t r = 0U; r < 256U; ++r) { - random_seed(&rand_state, salt, (uint16_t)r, passwd, passwd_len); + random_seed(&rand_state, nonce, (uint16_t)r, passwd, passwd_len); crypt_state->rotation_bwd[0U][255U - r] = crypt_state->rotation_fwd[0U][r] = (uint8_t)random_next(&rand_state); crypt_state->rotation_bwd[1U][255U - r] = crypt_state->rotation_fwd[1U][r] = 0U; for (size_t i = 0U; i < 256U; ++i) @@ -232,7 +235,7 @@ static int initialize_state(crypt_state_t* const crypt_state, const uint64_t sal } /* set up stepping */ - random_seed(&rand_state, salt, 256U, passwd, passwd_len); + random_seed(&rand_state, nonce, 256U, passwd, passwd_len); for (size_t i = 0U; i < 256U; ++i) { const size_t j = random_next(&rand_state) % (i + 1U); @@ -292,24 +295,24 @@ static FORCE_INLINE uint8_t process_dec(crypt_state_t* const crypt_state, uint8_ // Public API // ========================================================================== -int slunkcrypt_generate_salt(uint64_t* const seed) +int slunkcrypt_generate_nonce(uint64_t* const nonce) { - if (!seed) + if (!nonce) { return SLUNKCRYPT_FAILURE; } do { - if (slunkcrypt_random_bytes((uint8_t*)seed, sizeof(uint64_t)) != 0) + if (slunkcrypt_random_bytes((uint8_t*)nonce, sizeof(uint64_t)) != 0) { return SLUNKCRYPT_FAILURE; } } - while (!(*seed)); + while (!(*nonce)); return SLUNKCRYPT_SUCCESS; } -slunkcrypt_t slunkcrypt_alloc(const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len) +slunkcrypt_t slunkcrypt_alloc(const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len) { if ((!passwd) || (passwd_len < SLUNKCRYPT_PWDLEN_MIN) || (passwd_len > SLUNKCRYPT_PWDLEN_MAX)) { @@ -320,7 +323,7 @@ slunkcrypt_t slunkcrypt_alloc(const uint64_t salt, const uint8_t *const passwd, { return SLUNKCRYPT_NULL; } - if (initialize_state(state, salt, passwd, passwd_len) == SLUNKCRYPT_SUCCESS) + if (initialize_state(state, nonce, passwd, passwd_len) == SLUNKCRYPT_SUCCESS) { return ((slunkcrypt_t)state); } @@ -331,14 +334,14 @@ slunkcrypt_t slunkcrypt_alloc(const uint64_t salt, const uint8_t *const passwd, } } -int slunkcrypt_reset(const slunkcrypt_t context, const uint64_t salt, const uint8_t *const passwd, const size_t passwd_len) +int slunkcrypt_reset(const slunkcrypt_t context, const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len) { crypt_state_t* const state = (crypt_state_t*)context; if ((!state) || (!passwd) || (passwd_len < SLUNKCRYPT_PWDLEN_MIN) || (passwd_len > SLUNKCRYPT_PWDLEN_MAX)) { return SLUNKCRYPT_FAILURE; } - const int result = initialize_state(state, salt, passwd, passwd_len); + const int result = initialize_state(state, nonce, passwd, passwd_len); if (result != SLUNKCRYPT_SUCCESS) { slunkcrypt_bzero(state, sizeof(crypt_state_t));