Added build scripts for FreeBSD, Solaris and MacOS X platforms.
[slunkcrypt.git] / libslunkcrypt / src / keygen.c
blob8fa45f368a90baa765f02a62cf042db22d203bd1
1 /******************************************************************************/
2 /* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
3 /* This work has been released under the CC0 1.0 Universal license! */
4 /******************************************************************************/
6 /* Internal */
7 #include "keygen.h"
8 #include "compiler.h"
10 /* CRT */
11 #include <limits.h>
13 /* Type */
14 typedef struct
16 uint64_t hi, lo;
18 uint128_t;
20 // ==========================================================================
21 // 128-Bit math support
22 // ==========================================================================
24 #if defined(__GNUC__) && defined(__SIZEOF_INT128__)
25 # define HAVE_UINT128_SUPPORT 1
26 # define PACK_U128(X) ((((__uint128_t)(X).hi) << 64) | (X).lo)
27 #endif
29 static INLINE void multiply_u128(uint128_t *const out, const uint128_t lhs, const uint128_t rhs)
31 #ifdef HAVE_UINT128_SUPPORT
32 const __uint128_t product = PACK_U128(lhs) * PACK_U128(rhs);
33 *out = (uint128_t) { product >> 64, product };
34 #else
35 const uint64_t lolo = (lhs.lo & 0xFFFFFFFF) * (rhs.lo & 0xFFFFFFFF);
36 const uint64_t hilo = (lhs.lo >> 32U) * (rhs.lo & 0xFFFFFFFF);
37 const uint64_t lohi = (lhs.lo & 0xFFFFFFFF) * (rhs.lo >> 32U);
38 const uint64_t hihi = (lhs.lo >> 32U) * (rhs.lo >> 32U);
39 const uint64_t crss = (lolo >> 32U) + (hilo & 0xFFFFFFFF) + lohi;
40 out->hi = (hilo >> 32U) + (crss >> 32) + hihi;
41 out->lo = (crss << 32U) | (lolo & 0xFFFFFFFF);
42 out->hi += (lhs.hi * rhs.lo) + (lhs.lo * rhs.hi); /* 128x128=128 */
43 #endif
46 // ==========================================================================
47 // Hash function
48 // ==========================================================================
50 static const uint128_t HASH_OFFSETBASE_128 = { 0x6C62272E07BB0142, 0x62B821756295C58D };
51 static const uint128_t HASH_MAGICPRIME_128 = { 0x0000000001000000, 0x000000000000013B };
53 static INLINE void hash_update_u64(uint128_t* const hash, uint64_t value)
55 size_t i;
56 for (i = 0U; i < sizeof(uint64_t); ++i, value >>= CHAR_BIT)
58 hash->lo ^= (uint8_t)(value & 0xFF);
59 multiply_u128(hash, *hash, HASH_MAGICPRIME_128);
63 static INLINE void hash_update_str(uint128_t *const hash, const uint8_t *const data, const size_t data_len)
65 size_t i;
66 for (i = 0U; i < data_len; ++i)
68 hash->lo ^= data[i];
69 multiply_u128(hash, *hash, HASH_MAGICPRIME_128);
73 static INLINE uint128_t hash_code(const uint128_t *const seed, const uint8_t *const data, const size_t data_len)
75 uint128_t hash = HASH_OFFSETBASE_128;
76 hash_update_u64(&hash, seed->lo);
77 hash_update_u64(&hash, seed->hi);
78 hash_update_str(&hash, data, data_len);
79 return hash;
82 // ==========================================================================
83 // Key derivation
84 // ==========================================================================
86 static INLINE uint64_t keygen_loop(uint64_t seed, const uint64_t i, const uint8_t *const passwd, const size_t passwd_len)
88 uint128_t hash = { seed, i };
89 size_t u;
90 for (u = 0U, seed = 0U; u < 99971U; ++u)
92 hash = hash_code(&hash, passwd, passwd_len);
93 seed ^= hash.hi ^ hash.lo;
95 return seed;
98 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)
100 key->a = keygen_loop(salt, 0x162603FA1CDA99D3 + (uint64_t)pepper, passwd, passwd_len);
101 key->b = keygen_loop(salt, 0xBFDEC4A6C1A46E09 + (uint64_t)pepper, passwd, passwd_len);
102 key->c = keygen_loop(salt, 0x6BA17D11624973EE + (uint64_t)pepper, passwd, passwd_len);