1 /******************************************************************************/
2 /* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
3 /* This work has been released under the CC0 1.0 Universal license! */
4 /******************************************************************************/
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)
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
};
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 */
46 // ==========================================================================
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
)
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
)
66 for (i
= 0U; i
< data_len
; ++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
);
82 // ==========================================================================
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
};
90 for (u
= 0U, seed
= 0U; u
< 99971U; ++u
)
92 hash
= hash_code(&hash
, passwd
, passwd_len
);
93 seed
^= hash
.hi
^ hash
.lo
;
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
);