1 /******************************************************************************/
2 /* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
3 /* This work has been released under the CC0 1.0 Universal license! */
4 /******************************************************************************/
7 #include "../include/slunkcrypt.h"
15 /* Compiler compatibility */
17 # define FORCE_INLINE __forceinline
18 # define UNUSED __pragma(warning(suppress: 4189))
19 #elif defined(__GNUC__)
20 # define FORCE_INLINE __attribute__((always_inline)) inline
21 # define UNUSED __attribute__((unused))
23 # define FORCE_INLINE inline
28 const uint16_t SLUNKCRYPT_VERSION_MAJOR
= MY_VERSION_MAJOR
;
29 const uint16_t SLUNKCRYPT_VERSION_MINOR
= MY_VERSION_MINOR
;
30 const uint16_t SLUNKCRYPT_VERSION_PATCH
= MY_VERSION_PATCH
;
31 const char *const SLUNKCRYPT_BUILD
= __DATE__
" " __TIME__
;
34 #define HASH_MAGIC_PRIME 0x00000100000001B3ull
35 #define HASH_OFFSET_BASE 0xCBF29CE484222325ull
38 #define BOOLIFY(X) (!!(X))
40 // ==========================================================================
42 // ==========================================================================
52 uint32_t x
, y
, z
, w
, v
, d
;
59 uint8_t wheel
[256U][256U];
65 // ==========================================================================
67 // ==========================================================================
69 volatile int g_slunkcrypt_abort_flag
= 0;
71 #define CHECK_ABORTED() do \
73 if (g_slunkcrypt_abort_flag) \
80 // ==========================================================================
81 // Byte access (endianness agnostic)
82 // ==========================================================================
84 static FORCE_INLINE
uint32_t lower_u64(const uint64_t value
)
86 return (uint32_t)(value
& 0xFFFFFFFF);
89 static FORCE_INLINE
uint32_t upper_u64(const uint64_t value
)
91 return (uint32_t)((value
>> 32U) & 0xFFFFFFFF);
94 static FORCE_INLINE
uint8_t byte_u16(const uint16_t value
, const size_t off
)
96 assert(off
< sizeof(uint16_t));
97 return (uint8_t)((value
>> (CHAR_BIT
* off
)) & 0xFF);
100 static FORCE_INLINE
uint8_t byte_u64(const uint64_t value
, const size_t off
)
102 assert(off
< sizeof(uint64_t));
103 return (uint8_t)((value
>> (CHAR_BIT
* off
)) & 0xFF);
106 // ==========================================================================
108 // ==========================================================================
110 static FORCE_INLINE
void hash_update_str(uint64_t* const hash
, const uint8_t *const data
, const size_t data_len
)
113 for (i
= 0U; i
< data_len
; ++i
)
115 *hash
= ((*hash
) ^ data
[i
]) * HASH_MAGIC_PRIME
;
119 static FORCE_INLINE
void hash_update_u64(uint64_t *const hash
, const uint64_t value
)
122 for (i
= 0U; i
< sizeof(uint64_t); ++i
)
124 *hash
= ((*hash
) ^ byte_u64(value
, i
)) * HASH_MAGIC_PRIME
;
128 static FORCE_INLINE
void hash_update_u16(uint64_t *const hash
, const uint16_t value
)
131 for (i
= 0U; i
< sizeof(uint16_t); ++i
)
133 *hash
= ((*hash
) ^ byte_u16(value
, i
)) * HASH_MAGIC_PRIME
;
137 static uint64_t hash_code_init(const uint64_t salt
, const uint16_t i
, const uint8_t *const data
, const size_t data_len
)
139 uint64_t hash
= HASH_OFFSET_BASE
;
140 hash_update_u64(&hash
, salt
);
141 hash_update_u16(&hash
, i
);
142 hash_update_str(&hash
, data
, data_len
);
146 static uint64_t hash_code_next(const uint64_t salt
, const uint8_t *const data
, const size_t data_len
)
148 uint64_t hash
= HASH_OFFSET_BASE
;
149 hash_update_u64(&hash
, salt
);
150 hash_update_str(&hash
, data
, data_len
);
154 // ==========================================================================
156 // ==========================================================================
158 static FORCE_INLINE
uint64_t keygen_loop(uint64_t salt
, const uint16_t i
, const uint8_t *const passwd
, const size_t passwd_len
)
161 uint64_t result
= salt
= hash_code_init(salt
, i
, passwd
, passwd_len
);
162 for (u
= 1U; u
< 99971U; ++u
)
164 result
^= salt
= hash_code_next(salt
, passwd
, passwd_len
);
169 static void generate_key(key_data_t
*const key
, const uint64_t salt
, const uint16_t pepper
, const uint8_t *const passwd
, const size_t passwd_len
)
171 key
->a
= keygen_loop(salt
, (pepper
& 0x3FFF) | 0x0000, passwd
, passwd_len
);
172 key
->b
= keygen_loop(salt
, (pepper
& 0x3FFF) | 0x4000, passwd
, passwd_len
);
173 key
->c
= keygen_loop(salt
, (pepper
& 0x3FFF) | 0x8000, passwd
, passwd_len
);
176 // ==========================================================================
177 // Deterministic random bit generator
178 // ==========================================================================
180 static void random_init(rand_state_t
*const state
, const key_data_t
*const key
)
182 slunkcrypt_bzero(state
, sizeof(rand_state_t
));
183 state
->x
= lower_u64(key
->a
);
184 state
->y
= upper_u64(key
->a
);
185 state
->z
= lower_u64(key
->b
);
186 state
->w
= upper_u64(key
->b
);
187 state
->v
= lower_u64(key
->c
);
188 state
->d
= upper_u64(key
->c
);
191 static uint32_t random_next(rand_state_t
*const state
)
193 const uint32_t t
= state
->x
^ (state
->x
>> 2);
198 state
->v
^= (state
->v
<< 4) ^ t
^ (t
<< 1);
199 return (state
->d
+= 0x000587C5) + state
->v
;
202 static 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
)
208 generate_key(&key
, salt
++, pepper
, passwd
, passwd_len
);
209 random_init(state
, &key
);
210 slunkcrypt_bzero(&key
, sizeof(key_data_t
));
212 while (!(state
->x
|| state
->y
|| state
->z
|| state
->w
|| state
->v
));
213 for (i
= 0U; i
< 97U; ++i
)
215 UNUSED
volatile uint32_t q
= random_next(state
);
219 // ==========================================================================
221 // ==========================================================================
223 static int initialize_state(crypt_state_t
*const state
, const uint64_t nonce
, const uint8_t *const passwd
, const size_t passwd_len
, const int mode
)
225 uint8_t temp
[256U][256U];
227 const int reverse
= BOOLIFY(mode
);
229 /* initialize state */
230 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));
231 state
->reverse_mode
= reverse
;
233 /* initialize counter */
234 random_seed(&state
->random
, nonce
, (uint16_t)(-1), passwd
, passwd_len
);
235 state
->counter
= random_next(&state
->random
);
237 /* set up the wheel permutations */
238 for (r
= 0U; r
< 256U; ++r
)
240 random_seed(&state
->random
, nonce
, (uint16_t)r
, passwd
, passwd_len
);
241 for (i
= 0U; i
< 256U; ++i
)
243 const size_t j
= random_next(&state
->random
) % (i
+ 1U);
246 state
->wheel
[r
][i
] = state
->wheel
[r
][j
];
248 state
->wheel
[r
][j
] = (uint8_t)i
;
253 /* reverse the wheels, if requested */
256 for (r
= 0U; r
< 256U; ++r
)
258 for (i
= 0U; i
< 256U; ++i
)
260 temp
[r
][state
->wheel
[r
][i
]] = (uint8_t)i
;
263 for (r
= 0U; r
< 256U; ++r
)
265 memcpy(state
->wheel
[255U - r
], temp
[r
], 256U);
267 slunkcrypt_bzero(temp
, sizeof(temp
));
271 random_seed(&state
->random
, nonce
, 256U, passwd
, passwd_len
);
272 return SLUNKCRYPT_SUCCESS
;
276 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));
277 return SLUNKCRYPT_ABORTED
;
280 // ==========================================================================
282 // ==========================================================================
284 static FORCE_INLINE
void update_offset(uint8_t *const offset
, uint32_t seed
, rand_state_t
*const state
, const int reverse
)
287 for (i
= 0U; i
< 256U; ++i
, seed
>>= CHAR_BIT
)
289 if (i
&& (!(i
& 3U)))
291 seed
= random_next(state
);
293 offset
[reverse
? (255U - i
) : i
] = (uint8_t)seed
;
297 static FORCE_INLINE
uint8_t process_next_symbol(crypt_state_t
*const state
, uint8_t value
)
299 uint8_t offset
[256U];
301 update_offset(offset
, state
->counter
++, &state
->random
, state
->reverse_mode
);
302 for (i
= 0U; i
< 256U; ++i
)
304 value
= (state
->wheel
[i
][(value
+ offset
[i
]) & 0xFF] - offset
[i
]) & 0xFF;
309 // ==========================================================================
311 // ==========================================================================
313 int slunkcrypt_generate_nonce(uint64_t *const nonce
)
317 return SLUNKCRYPT_FAILURE
;
321 if (slunkcrypt_random_bytes((uint8_t*)nonce
, sizeof(uint64_t)) != sizeof(uint64_t))
323 return SLUNKCRYPT_FAILURE
;
327 return SLUNKCRYPT_SUCCESS
;
330 slunkcrypt_t
slunkcrypt_alloc(const uint64_t nonce
, const uint8_t *const passwd
, const size_t passwd_len
, const int mode
)
332 crypt_state_t
* state
= NULL
;
333 if ((!passwd
) || (passwd_len
< SLUNKCRYPT_PWDLEN_MIN
) || (passwd_len
> SLUNKCRYPT_PWDLEN_MAX
) || (mode
< SLUNKCRYPT_ENCRYPT
) || (mode
> SLUNKCRYPT_DECRYPT
))
335 return SLUNKCRYPT_NULL
;
337 if (!(state
= (crypt_state_t
*)malloc(sizeof(crypt_state_t
))))
339 return SLUNKCRYPT_NULL
;
341 if (initialize_state(state
, nonce
, passwd
, passwd_len
, mode
) == SLUNKCRYPT_SUCCESS
)
343 return ((slunkcrypt_t
)state
);
347 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));
348 return SLUNKCRYPT_NULL
;
352 int slunkcrypt_reset(const slunkcrypt_t context
, const uint64_t nonce
, const uint8_t *const passwd
, const size_t passwd_len
, const int mode
)
354 crypt_state_t
*const state
= (crypt_state_t
*)context
;
355 int result
= SLUNKCRYPT_FAILURE
;
356 if ((!state
) || (!passwd
) || (passwd_len
< SLUNKCRYPT_PWDLEN_MIN
) || (passwd_len
> SLUNKCRYPT_PWDLEN_MAX
) || (mode
< SLUNKCRYPT_ENCRYPT
) || (mode
> SLUNKCRYPT_DECRYPT
))
358 return SLUNKCRYPT_FAILURE
;
360 if ((result
= initialize_state(state
, nonce
, passwd
, passwd_len
, mode
)) != SLUNKCRYPT_SUCCESS
)
362 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));
367 int slunkcrypt_process(const slunkcrypt_t context
, const uint8_t *const input
, uint8_t *const output
, size_t length
)
369 crypt_state_t
*const state
= (crypt_state_t
*)context
;
372 return SLUNKCRYPT_FAILURE
;
378 for (i
= 0; i
< length
; ++i
)
380 output
[i
] = process_next_symbol(state
, input
[i
]);
385 return SLUNKCRYPT_SUCCESS
;
388 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));
389 return SLUNKCRYPT_ABORTED
;
392 int slunkcrypt_inplace(const slunkcrypt_t context
, uint8_t *const buffer
, size_t length
)
394 crypt_state_t
*const state
= (crypt_state_t
*)context
;
397 return SLUNKCRYPT_FAILURE
;
403 for (i
= 0; i
< length
; ++i
)
405 buffer
[i
] = process_next_symbol(state
, buffer
[i
]);
410 return SLUNKCRYPT_SUCCESS
;
413 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));
414 return SLUNKCRYPT_ABORTED
;
417 void slunkcrypt_free(const slunkcrypt_t context
)
419 crypt_state_t
*const state
= (crypt_state_t
*)context
;
422 slunkcrypt_bzero(state
, sizeof(crypt_state_t
));