2021-04-17 15:13:13 +02:00
|
|
|
/******************************************************************************/
|
|
|
|
/* 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;
|
|
|
|
}
|
2022-10-25 22:09:40 +02:00
|
|
|
hash128_t;
|
2021-04-17 15:13:13 +02:00
|
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
// 128-Bit math support
|
|
|
|
// ==========================================================================
|
|
|
|
|
2022-04-23 17:30:51 +02:00
|
|
|
#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
|
2022-10-25 22:09:40 +02:00
|
|
|
# define HAVE_UINT128_T 1
|
|
|
|
# define LOAD_U128(X) ((((__uint128_t)(X).hi) << 64) | (X).lo)
|
2022-10-16 19:29:06 +02:00
|
|
|
#else
|
|
|
|
# pragma message("Compiler does not support 128-bit math -> using fallback!")
|
2022-04-23 17:30:51 +02:00
|
|
|
#endif
|
2021-04-17 15:13:13 +02:00
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
static INLINE void multiply_u128(hash128_t *const out, const hash128_t lhs, const hash128_t *const rhs)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
2022-10-25 22:09:40 +02:00
|
|
|
#ifdef HAVE_UINT128_T
|
|
|
|
const __uint128_t product = LOAD_U128(lhs) * LOAD_U128(*rhs);
|
|
|
|
out->lo = (uint64_t)product;
|
|
|
|
out->hi = (uint64_t)(product >> 64);
|
2021-04-17 15:13:13 +02:00
|
|
|
#else
|
2022-10-25 22:09:40 +02:00
|
|
|
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);
|
2021-04-17 15:13:13 +02:00
|
|
|
const uint64_t crss = (lolo >> 32U) + (hilo & 0xFFFFFFFF) + lohi;
|
|
|
|
out->hi = (hilo >> 32U) + (crss >> 32) + hihi;
|
|
|
|
out->lo = (crss << 32U) | (lolo & 0xFFFFFFFF);
|
2022-10-25 22:09:40 +02:00
|
|
|
out->hi += (lhs.hi * rhs->lo) + (lhs.lo * rhs->hi); /* 128x128=128 */
|
2021-04-17 15:13:13 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
// Hash function
|
|
|
|
// ==========================================================================
|
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
static const hash128_t HASH_OFFSETBASE_128 = { UINT64_C(0x6C62272E07BB0142), UINT64_C(0x62B821756295C58D) };
|
|
|
|
static const hash128_t HASH_MAGICPRIME_128 = { UINT64_C(0x0000000001000000), UINT64_C(0x000000000000013B) };
|
2021-04-17 15:13:13 +02:00
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
#define HASH_UPDATE(X) do \
|
|
|
|
{ \
|
|
|
|
hash->lo ^= (X); \
|
|
|
|
multiply_u128(hash, *hash, &HASH_MAGICPRIME_128); \
|
|
|
|
} \
|
|
|
|
while(0)
|
|
|
|
|
|
|
|
static INLINE void hash_update_u64(hash128_t *const hash, uint64_t value)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0U; i < sizeof(uint64_t); ++i, value >>= CHAR_BIT)
|
|
|
|
{
|
2022-10-25 22:09:40 +02:00
|
|
|
HASH_UPDATE((uint8_t)value);
|
2021-04-17 15:13:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
static INLINE void hash_update_str(hash128_t *const hash, const uint8_t *const data, const size_t data_len)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0U; i < data_len; ++i)
|
|
|
|
{
|
2022-10-25 22:09:40 +02:00
|
|
|
HASH_UPDATE(data[i]);
|
2021-04-17 15:13:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
static INLINE hash128_t hash_code(const hash128_t *const seed, const uint8_t *const data, const size_t data_len)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
2022-10-25 22:09:40 +02:00
|
|
|
hash128_t hash = HASH_OFFSETBASE_128;
|
2021-04-17 15:13:13 +02:00
|
|
|
hash_update_u64(&hash, seed->lo);
|
|
|
|
hash_update_u64(&hash, seed->hi);
|
|
|
|
hash_update_str(&hash, data, data_len);
|
|
|
|
return hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
// Key derivation
|
|
|
|
// ==========================================================================
|
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
static INLINE uint64_t keygen_loop(uint64_t seed, const uint64_t i, const uint8_t *const passwd, const size_t passwd_len, const size_t rounds)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
2022-10-25 22:09:40 +02:00
|
|
|
hash128_t hash = { seed, i };
|
2021-04-17 15:13:13 +02:00
|
|
|
size_t u;
|
2022-10-25 22:09:40 +02:00
|
|
|
for (u = 0U, seed = 0U; u < rounds; ++u)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
|
|
|
hash = hash_code(&hash, passwd, passwd_len);
|
|
|
|
seed ^= hash.hi ^ hash.lo;
|
|
|
|
}
|
|
|
|
return seed;
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:09:40 +02:00
|
|
|
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, const size_t rounds)
|
2021-04-17 15:13:13 +02:00
|
|
|
{
|
2022-10-25 22:09:40 +02:00
|
|
|
key->a = keygen_loop(salt, 0x162603FA1CDA99D3 + (uint64_t)pepper, passwd, passwd_len, rounds);
|
|
|
|
key->b = keygen_loop(salt, 0xBFDEC4A6C1A46E09 + (uint64_t)pepper, passwd, passwd_len, rounds);
|
|
|
|
key->c = keygen_loop(salt, 0x6BA17D11624973EE + (uint64_t)pepper, passwd, passwd_len, rounds);
|
2021-04-17 15:13:13 +02:00
|
|
|
}
|