diff --git a/libslunkcrypt/libSlunkCrypt.vcxproj b/libslunkcrypt/libSlunkCrypt.vcxproj index de4b636..cd70227 100644 --- a/libslunkcrypt/libSlunkCrypt.vcxproj +++ b/libslunkcrypt/libSlunkCrypt.vcxproj @@ -44,11 +44,14 @@ + + + diff --git a/libslunkcrypt/libSlunkCrypt.vcxproj.filters b/libslunkcrypt/libSlunkCrypt.vcxproj.filters index 78e3bd9..9e5bb18 100644 --- a/libslunkcrypt/libSlunkCrypt.vcxproj.filters +++ b/libslunkcrypt/libSlunkCrypt.vcxproj.filters @@ -21,6 +21,9 @@ Source Files + + Source Files + @@ -32,5 +35,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/libslunkcrypt/src/compiler.h b/libslunkcrypt/src/compiler.h new file mode 100644 index 0000000..ad2e215 --- /dev/null +++ b/libslunkcrypt/src/compiler.h @@ -0,0 +1,26 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef INC_SLUNKCRYPT_COMPILER_H +#define INC_SLUNKCRYPT_COMPILER_H + +/* Intel(R) oneAPI DPC++/C++ Compiler */ +#if defined(__INTEL_LLVM_COMPILER) && (!defined(__GNUC__)) +# define __GNUC__ 9 +#endif + +/* Compiler compatibility */ +#if defined(_MSC_VER) && (!defined(__GNUC__)) +# define INLINE __inline +# define UNUSED __pragma(warning(suppress: 4189)) +#elif defined(__GNUC__) +# define INLINE __inline__ +# define UNUSED __attribute__((unused)) +#else +# define INLINE inline +# define UNUSED +#endif + +#endif diff --git a/libslunkcrypt/src/junk.c b/libslunkcrypt/src/junk.c index 2c8b7f2..112fdd9 100644 --- a/libslunkcrypt/src/junk.c +++ b/libslunkcrypt/src/junk.c @@ -11,14 +11,18 @@ #endif /* Internal */ -#include "../include/slunkcrypt.h" +#include "slunkcrypt.h" +#include "compiler.h" /* CRT */ #include #include #include -/* Platform compatibility */ +// ========================================================================== +// Platform compatibility +// ========================================================================== + #ifdef _WIN32 # include #else @@ -26,11 +30,30 @@ # include #endif -/* Compiler compatibility */ +/* detect destructor support */ +#undef ATTRIB_DESTRUCTOR #if defined(__GNUC__) || defined(__clang__) -# define HAVE_DESTRUCTOR 1 -#else -# define HAVE_DESTRUCTOR 0 +# define ATTRIB_DESTRUCTOR __attribute__((destructor)) +#endif + +/* detect getrandom() support */ +#undef SYS_GETRANDOM +#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) +# define SYS_GETRANDOM 1 +# include +#elif defined(__FreeBSD__) && (__FreeBSD__ >= 12) +# define SYS_GETRANDOM 1 +# include +#endif + +/* detect explicit_bzero() support */ +#undef EXPLICIT_BZERO +#if defined(_WIN32) && defined(SecureZeroMemory) +# define EXPLICIT_BZERO SecureZeroMemory +#elif defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) +# define EXPLICIT_BZERO explicit_bzero +#elif defined(__FreeBSD__) && (__FreeBSD__ >= 11) +# define EXPLICIT_BZERO explicit_bzero #endif // ========================================================================== @@ -68,28 +91,13 @@ static void win32_call_once(CALL_ONCE_TYPE *const control, void (*init_routine)( // Random bytes // ========================================================================== -#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 CALL_ONCE_TYPE s_random_is_initialized = CALL_ONCE_INIT; #if defined(_WIN32) -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 +typedef BOOLEAN(WINAPI *rtlgenrandom_t)(void *buffer, ULONG buff_size); +static HMODULE s_advapi32 = NULL; +static rtlgenrandom_t s_rtlgenrandom = NULL; +#elif !defined(SYS_GETRANDOM) static const char *const DEV_RANDOM[] = { "/dev/urandom", "/dev/arandom", "/dev/random", NULL }; static int s_random_fd = -1; #endif @@ -98,13 +106,13 @@ static int s_random_fd = -1; static void exit_random_source(void) { #if defined(_WIN32) - s_rtl_genrandom = NULL; - if (s_dll_advapi32) + s_rtlgenrandom = NULL; + if (s_advapi32) { - FreeLibrary(s_dll_advapi32); - s_dll_advapi32 = NULL; + FreeLibrary(s_advapi32); + s_advapi32 = NULL; } -#elif !HAVE_GETRANDOM +#elif !defined(SYS_GETRANDOM) if (s_random_fd >= 0) { close(s_random_fd); @@ -117,11 +125,11 @@ static void exit_random_source(void) static void init_random_source(void) { #if defined(_WIN32) - if ((s_dll_advapi32 = LoadLibraryW(L"advapi32.dll"))) + if ((s_advapi32 = LoadLibraryW(L"advapi32.dll"))) { - s_rtl_genrandom = (rtl_genrandom_t)GetProcAddress(s_dll_advapi32, "SystemFunction036"); + s_rtlgenrandom = (rtlgenrandom_t) GetProcAddress(s_advapi32, "SystemFunction036"); } -#elif !HAVE_GETRANDOM +#elif !defined(SYS_GETRANDOM) for (size_t i = 0U; DEV_RANDOM[i]; ++i) { if ((s_random_fd = open(DEV_RANDOM[i], O_RDONLY)) >= 0) @@ -130,7 +138,7 @@ static void init_random_source(void) } } #endif -#if !HAVE_DESTRUCTOR +#if !defined(ATTRIB_DESTRUCTOR) atexit(exit_random_source); #endif } @@ -140,12 +148,12 @@ size_t slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length) { CALL_ONCE(&s_random_is_initialized, init_random_source); #if defined(_WIN32) - if (s_rtl_genrandom) + if (s_rtlgenrandom) { const ULONG buff_size = (ULONG)length; - return s_rtl_genrandom(buffer, buff_size) ? buff_size : 0U; + return s_rtlgenrandom(buffer, buff_size) ? buff_size : 0U; } -#elif HAVE_GETRANDOM +#elif defined(SYS_GETRANDOM) const ssize_t result = getrandom(buffer, length, 0U); return (result < 0) ? 0U : ((size_t)result); #else @@ -162,29 +170,12 @@ size_t slunkcrypt_random_bytes(uint8_t* const buffer, const size_t length) // Zero memory // ========================================================================== -#ifdef _WIN32 -# ifdef SecureZeroMemory -# define HAVE_EXPLICIT_BZERO 1 -# define explicit_bzero SecureZeroMemory -# else -# define HAVE_EXPLICIT_BZERO 0 -# endif -#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 buffer, const size_t length) { if ((buffer) && (length > 0U)) { -#if HAVE_EXPLICIT_BZERO - explicit_bzero(buffer, length); +#if defined(EXPLICIT_BZERO) + EXPLICIT_BZERO(buffer, length); #else volatile uint8_t* ptr = (volatile uint8_t*) buffer; for (size_t i = 0U; i < length; ++i) @@ -199,8 +190,8 @@ void slunkcrypt_bzero(void* const buffer, const size_t length) // Destructor // ========================================================================== -#if HAVE_DESTRUCTOR -__attribute__((destructor)) void slunkcrypt_destructor() +#if defined(ATTRIB_DESTRUCTOR) +ATTRIB_DESTRUCTOR void slunkcrypt_destructor() { exit_random_source(); } diff --git a/libslunkcrypt/src/keygen.c b/libslunkcrypt/src/keygen.c new file mode 100644 index 0000000..5bd3904 --- /dev/null +++ b/libslunkcrypt/src/keygen.c @@ -0,0 +1,101 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +/* Internal */ +#include "keygen.h" +#include "compiler.h" + +/* CRT */ +#include + +/* Type */ +typedef struct +{ + uint64_t hi, lo; +} +uint128_t; + +// ========================================================================== +// 128-Bit math support +// ========================================================================== + +#define READ_U128(X) ((((__uint128_t)(X).hi) << 64U) | ((__uint128_t)(X).lo)) + +static INLINE void multiply_u128(uint128_t *const out, const uint128_t lhs, const uint128_t rhs) +{ +#if defined(__GNUC__) && defined(__SIZEOF_INT128__) + const __uint128_t tmp = READ_U128(lhs) * READ_U128(rhs); + out->hi = (uint64_t)(tmp >> 64U); + out->lo = (uint64_t)(tmp & 0xFFFFFFFFFFFFFFFF); +#else + const uint64_t lolo = (lhs.lo & 0xFFFFFFFF) * (rhs.lo & 0xFFFFFFFF); + const uint64_t hilo = (lhs.lo >> 32U) * (rhs.lo & 0xFFFFFFFF); + const uint64_t lohi = (lhs.lo & 0xFFFFFFFF) * (rhs.lo >> 32U); + const uint64_t hihi = (lhs.lo >> 32U) * (rhs.lo >> 32U); + const uint64_t crss = (lolo >> 32U) + (hilo & 0xFFFFFFFF) + lohi; + out->hi = (hilo >> 32U) + (crss >> 32) + hihi; + out->lo = (crss << 32U) | (lolo & 0xFFFFFFFF); + out->hi += (lhs.hi * rhs.lo) + (lhs.lo * rhs.hi); /* 128x128=128 */ +#endif +} + +// ========================================================================== +// Hash function +// ========================================================================== + +static const uint128_t HASH_OFFSETBASE_128 = { 0x6C62272E07BB0142, 0x62B821756295C58D }; +static const uint128_t HASH_MAGICPRIME_128 = { 0x0000000001000000, 0x000000000000013B }; + +static INLINE void hash_update_u64(uint128_t* const hash, uint64_t value) +{ + size_t i; + for (i = 0U; i < sizeof(uint64_t); ++i, value >>= CHAR_BIT) + { + hash->lo ^= (uint8_t)(value & 0xFF); + multiply_u128(hash, *hash, HASH_MAGICPRIME_128); + } +} + +static INLINE void hash_update_str(uint128_t *const hash, const uint8_t *const data, const size_t data_len) +{ + size_t i; + for (i = 0U; i < data_len; ++i) + { + hash->lo ^= data[i]; + multiply_u128(hash, *hash, HASH_MAGICPRIME_128); + } +} + +static INLINE uint128_t hash_code(const uint128_t *const seed, const uint8_t *const data, const size_t data_len) +{ + uint128_t hash = HASH_OFFSETBASE_128; + hash_update_u64(&hash, seed->lo); + hash_update_u64(&hash, seed->hi); + hash_update_str(&hash, data, data_len); + return hash; +} + +// ========================================================================== +// Key derivation +// ========================================================================== + +static INLINE uint64_t keygen_loop(uint64_t seed, const uint64_t i, const uint8_t *const passwd, const size_t passwd_len) +{ + uint128_t hash = { seed, i }; + size_t u; + for (u = 0U, seed = 0U; u < 99971U; ++u) + { + hash = hash_code(&hash, passwd, passwd_len); + seed ^= hash.hi ^ hash.lo; + } + return seed; +} + +void slunkcrypt_keygen(keydata_t *const key, const uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len) +{ + key->a = keygen_loop(salt, 0x162603FA1CDA99D3 + (uint64_t)pepper, passwd, passwd_len); + key->b = keygen_loop(salt, 0xBFDEC4A6C1A46E09 + (uint64_t)pepper, passwd, passwd_len); + key->c = keygen_loop(salt, 0x6BA17D11624973EE + (uint64_t)pepper, passwd, passwd_len); +} diff --git a/libslunkcrypt/src/keygen.h b/libslunkcrypt/src/keygen.h new file mode 100644 index 0000000..6c572bd --- /dev/null +++ b/libslunkcrypt/src/keygen.h @@ -0,0 +1,20 @@ +/******************************************************************************/ +/* SlunkCrypt, by LoRd_MuldeR */ +/* This work has been released under the CC0 1.0 Universal license! */ +/******************************************************************************/ + +#ifndef INC_SLUNKCRYPT_KEYGEN_H +#define INC_SLUNKCRYPT_KEYGEN_H + +#include +#include + +typedef struct +{ + uint64_t a, b, c; +} +keydata_t; + +void slunkcrypt_keygen(keydata_t *const key, const uint64_t salt, const uint16_t pepper, const uint8_t* const passwd, const size_t passwd_len); + +#endif diff --git a/libslunkcrypt/src/slunkcrypt.c b/libslunkcrypt/src/slunkcrypt.c index 4f07878..afefcbd 100644 --- a/libslunkcrypt/src/slunkcrypt.c +++ b/libslunkcrypt/src/slunkcrypt.c @@ -4,32 +4,16 @@ /******************************************************************************/ /* Internal */ -#include "../include/slunkcrypt.h" +#include "slunkcrypt.h" +#include "compiler.h" +#include "keygen.h" #include "version.h" /* CRT */ #include #include -#include -/* Intel(R) oneAPI DPC++/C++ Compiler */ -#if defined(__INTEL_LLVM_COMPILER) && (!defined(__GNUC__)) -# define __GNUC__ 9 -#endif - -/* Compiler compatibility */ -#if defined(_MSC_VER) && (!defined(__GNUC__)) -# define INLINE __inline -# define UNUSED __pragma(warning(suppress: 4189)) -#elif defined(__GNUC__) -# define INLINE __inline__ -# define UNUSED __attribute__((unused)) -#else -# define INLINE inline -# define UNUSED -#endif - -/* Version info */ +/* Version */ const uint16_t SLUNKCRYPT_VERSION_MAJOR = LIB_VERSION_MAJOR; const uint16_t SLUNKCRYPT_VERSION_MINOR = LIB_VERSION_MINOR; const uint16_t SLUNKCRYPT_VERSION_PATCH = LIB_VERSION_PATCH; @@ -42,12 +26,6 @@ const char *const SLUNKCRYPT_BUILD = __DATE__ ", " __TIME__; // Data structures // ========================================================================== -typedef struct -{ - uint64_t hi, lo; -} -uint128_t; - typedef struct { uint32_t x, y, z, w, v, d; @@ -92,108 +70,19 @@ static INLINE uint32_t upper_u64(const uint64_t value) return (uint32_t)(value >> 32U); } -static INLINE uint8_t byte_u64(const uint64_t value, const size_t off) -{ - assert(off < sizeof(uint64_t)); - return (uint8_t)((value >> (CHAR_BIT * off)) & 0xFF); -} - -// ========================================================================== -// 128-Bit math support -// ========================================================================== - -#define READ_U128(X) ((((__uint128_t)(X).hi) << 64U) | ((__uint128_t)(X).lo)) - -static INLINE void multiply_u128(uint128_t *const out, const uint128_t lhs, const uint128_t rhs) -{ -#if defined(__GNUC__) && defined(__SIZEOF_INT128__) - const __uint128_t tmp = READ_U128(lhs) * READ_U128(rhs); - out->hi = (uint64_t)(tmp >> 64U); - out->lo = (uint64_t)(tmp & 0xFFFFFFFFFFFFFFFF); -#else - const uint64_t lolo = (lhs.lo & 0xFFFFFFFF) * (rhs.lo & 0xFFFFFFFF); - const uint64_t hilo = (lhs.lo >> 32U) * (rhs.lo & 0xFFFFFFFF); - const uint64_t lohi = (lhs.lo & 0xFFFFFFFF) * (rhs.lo >> 32U); - const uint64_t hihi = (lhs.lo >> 32U) * (rhs.lo >> 32U); - const uint64_t crss = (lolo >> 32U) + (hilo & 0xFFFFFFFF) + lohi; - out->hi = (hilo >> 32U) + (crss >> 32) + hihi; - out->lo = (crss << 32U) | (lolo & 0xFFFFFFFF); - out->hi += (lhs.hi * rhs.lo) + (lhs.lo * rhs.hi); /* 128x128=128 */ -#endif -} - -// ========================================================================== -// Hash function -// ========================================================================== - -static const uint128_t HASH_OFFSETBASE_128 = { 0x6C62272E07BB0142, 0x62B821756295C58D }; -static const uint128_t HASH_MAGICPRIME_128 = { 0x0000000001000000, 0x000000000000013B }; - -static INLINE void hash_update_str(uint128_t *const hash, const uint8_t *const data, const size_t data_len) -{ - size_t i; - for (i = 0U; i < data_len; ++i) - { - hash->lo ^= data[i]; - multiply_u128(hash, *hash, HASH_MAGICPRIME_128); - } -} - -static INLINE void hash_update_u64(uint128_t *const hash, const uint64_t value) -{ - size_t i; - for (i = 0U; i < sizeof(uint64_t); ++i) - { - hash->lo ^= byte_u64(value, i); - multiply_u128(hash, *hash, HASH_MAGICPRIME_128); - } -} - -static INLINE uint128_t hash_code(const uint128_t *const salt, const uint8_t *const data, const size_t data_len) -{ - uint128_t hash = HASH_OFFSETBASE_128; - hash_update_u64(&hash, salt->lo); - hash_update_u64(&hash, salt->hi); - hash_update_str(&hash, data, data_len); - return hash; -} - -// ========================================================================== -// Key derivation -// ========================================================================== - -static INLINE uint64_t keygen_loop(uint64_t salt, const uint64_t pepper, const uint8_t *const passwd, const size_t passwd_len) -{ - uint128_t hash = { salt, pepper }; - size_t u; - for (u = 0U, salt = 0U; u < 99971U; ++u) - { - hash = hash_code(&hash, passwd, passwd_len); - salt ^= hash.hi ^ hash.lo; - } - return salt; -} - -static INLINE void generate_key(uint64_t *const key, const uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len) -{ - key[0U] = keygen_loop(salt, 0x162603FA1CDA99D3 + (uint64_t)pepper, passwd, passwd_len); - key[1U] = keygen_loop(salt, 0xBFDEC4A6C1A46E09 + (uint64_t)pepper, passwd, passwd_len); - key[2U] = keygen_loop(salt, 0x6BA17D11624973EE + (uint64_t)pepper, passwd, passwd_len); -} - // ========================================================================== // Deterministic random bit generator // ========================================================================== -static INLINE void random_init(rand_state_t *const state, const uint64_t *const key) +static INLINE void random_init(rand_state_t *const state, const keydata_t *const key) { slunkcrypt_bzero(state, sizeof(rand_state_t)); - state->x = lower_u64(key[0U]); - state->y = upper_u64(key[0U]); - state->z = lower_u64(key[1U]); - state->w = upper_u64(key[1U]); - state->v = lower_u64(key[2U]); - state->d = upper_u64(key[2U]); + state->x = lower_u64(key->a); + state->y = upper_u64(key->a); + state->z = lower_u64(key->b); + state->w = upper_u64(key->b); + state->v = lower_u64(key->c); + state->d = upper_u64(key->c); } static INLINE uint32_t random_next(rand_state_t *const state) @@ -210,12 +99,12 @@ static INLINE uint32_t random_next(rand_state_t *const state) static INLINE void random_seed(rand_state_t *const state, uint64_t salt, const uint16_t pepper, const uint8_t *const passwd, const size_t passwd_len) { size_t i; - uint64_t key[3U]; + keydata_t key; do { - generate_key(key, salt++, pepper, passwd, passwd_len); - random_init(state, key); - slunkcrypt_bzero(&key, 3U * sizeof(uint64_t)); + slunkcrypt_keygen(&key, salt++, pepper, passwd, passwd_len); + random_init(state, &key); + slunkcrypt_bzero(&key, sizeof(keydata_t)); } while (!(state->x || state->y || state->z || state->w || state->v)); for (i = 0U; i < 97U; ++i)