OSDN Git Service

Refactored key-derivation code into a separate file + some code clean-up.
authorLoRd_MuldeR <mulder2@gmx.de>
Sat, 17 Apr 2021 13:13:13 +0000 (15:13 +0200)
committerLoRd_MuldeR <mulder2@gmx.de>
Sat, 17 Apr 2021 13:13:13 +0000 (15:13 +0200)
libslunkcrypt/libSlunkCrypt.vcxproj
libslunkcrypt/libSlunkCrypt.vcxproj.filters
libslunkcrypt/src/compiler.h [new file with mode: 0644]
libslunkcrypt/src/junk.c
libslunkcrypt/src/keygen.c [new file with mode: 0644]
libslunkcrypt/src/keygen.h [new file with mode: 0644]
libslunkcrypt/src/slunkcrypt.c

index de4b636..cd70227 100644 (file)
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="src\junk.c" />
+    <ClCompile Include="src\keygen.c" />
     <ClCompile Include="src\slunkcrypt.c" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="include\slunkcrypt.h" />
     <ClInclude Include="include\slunkcrypt.hpp" />
+    <ClInclude Include="src\compiler.h" />
+    <ClInclude Include="src\keygen.h" />
     <ClInclude Include="src\version.h" />
   </ItemGroup>
   <PropertyGroup Label="Globals">
index 78e3bd9..9e5bb18 100644 (file)
@@ -21,6 +21,9 @@
     <ClCompile Include="src\junk.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\keygen.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="include\slunkcrypt.h">
     <ClInclude Include="include\slunkcrypt.hpp">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="src\keygen.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="src\compiler.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/libslunkcrypt/src/compiler.h b/libslunkcrypt/src/compiler.h
new file mode 100644 (file)
index 0000000..ad2e215
--- /dev/null
@@ -0,0 +1,26 @@
+/******************************************************************************/
+/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
+/* 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
index 2c8b7f2..112fdd9 100644 (file)
 #endif
 
 /* Internal */
-#include "../include/slunkcrypt.h"
+#include "slunkcrypt.h"
+#include "compiler.h"
 
 /* CRT */
 #include <string.h>
 #include <fcntl.h>
 #include <limits.h>
 
-/* Platform compatibility */
+// ==========================================================================
+// Platform compatibility
+// ==========================================================================
+
 #ifdef _WIN32
 #      include <Windows.h>
 #else
 #      include <pthread.h>
 #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 <sys/random.h>
+#elif defined(__FreeBSD__) && (__FreeBSD__ >= 12)
+#      define SYS_GETRANDOM 1
+#      include <sys/random.h>
+#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 <sys/random.h>
-#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 (file)
index 0000000..5bd3904
--- /dev/null
@@ -0,0 +1,101 @@
+/******************************************************************************/
+/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
+/* This work has been released under the CC0 1.0 Universal license!           */
+/******************************************************************************/
+
+/* Internal */
+#include "keygen.h"
+#include "compiler.h"
+
+/* CRT */
+#include <limits.h>
+
+/* 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 (file)
index 0000000..6c572bd
--- /dev/null
@@ -0,0 +1,20 @@
+/******************************************************************************/
+/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
+/* This work has been released under the CC0 1.0 Universal license!           */
+/******************************************************************************/
+
+#ifndef INC_SLUNKCRYPT_KEYGEN_H
+#define INC_SLUNKCRYPT_KEYGEN_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+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
index 4f07878..afefcbd 100644 (file)
@@ -4,32 +4,16 @@
 /******************************************************************************/
 
 /* Internal */
-#include "../include/slunkcrypt.h"
+#include "slunkcrypt.h"
+#include "compiler.h"
+#include "keygen.h"
 #include "version.h"
 
 /* CRT */
 #include <string.h>
 #include <limits.h>
-#include <assert.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
-
-/* 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;
@@ -44,12 +28,6 @@ const char *const SLUNKCRYPT_BUILD = __DATE__ ", " __TIME__;
 
 typedef struct
 {
-       uint64_t hi, lo;
-}
-uint128_t;
-
-typedef struct
-{
        uint32_t x, y, z, w, v, d;
 }
 rand_state_t;
@@ -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)