Now revised version is on https://github.com/grafi-tt/melty2
-
-
Save grafi-tt/886e0ced880195eac50ffae50e4d101f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Written by Shunsuke Shimizu. | |
* | |
* To the extent possible under law, the author has dedicated all copyright | |
* and related and neighboring rights to this software to the public domain | |
* worldwide. This software is distributed without any warranty. | |
* | |
* See <http://creativecommons.org/publicdomain/zero/1.0/>. | |
*/ | |
#include <stddef.h> | |
#include <stdint.h> | |
#include <unif01.h> | |
#include <bbattery.h> | |
typedef struct melty2_name_ { | |
uint32_t v[8]; | |
} melty2_name; | |
typedef struct melty2_key_ { | |
uint32_t v_[6]; | |
} melty2_key; | |
static inline uint32_t melty2_rotl_(uint32_t v, int n) { | |
return (v << n) | (v >> (32 - n)); | |
} | |
static void melty2_inject_(uint32_t *v, uint32_t a, uint32_t b) { | |
v[0] += a; | |
v[1] -= a; | |
v[2] += b; | |
v[3] -= b; | |
} | |
static void melty2_permute_(uint32_t *v) { | |
v[0] = melty2_rotl_(v[0], 7); | |
v[1] += v[0]; | |
v[2] ^= v[1]; | |
v[2] = melty2_rotl_(v[2], 9); | |
v[3] += v[2]; | |
v[4] ^= v[3]; | |
v[4] = melty2_rotl_(v[4], 13); | |
v[5] += v[4]; | |
v[0] ^= v[5]; | |
v[0] = melty2_rotl_(v[0], 18); | |
v[1] -= v[0]; | |
v[2] ^= v[1]; | |
v[2] = melty2_rotl_(v[2], 7); | |
v[3] -= v[2]; | |
v[4] ^= v[3]; | |
v[4] = melty2_rotl_(v[4], 9); | |
v[5] -= v[4]; | |
v[0] ^= v[5]; | |
v[0] = melty2_rotl_(v[0], 13); | |
v[1] += v[0]; | |
v[2] ^= v[1]; | |
v[2] = melty2_rotl_(v[2], 18); | |
v[3] += v[2]; | |
v[4] ^= v[3]; | |
v[4] = melty2_rotl_(v[4], 12); | |
v[5] += v[4]; | |
v[0] ^= v[5]; | |
} | |
static inline void melty2_initkey(melty2_key *key, const melty2_name *name, uint64_t global_seed, uint64_t global_ctr) { | |
uint32_t v0[6] = {2718281828, 2718281828, 2718281828, 2718281828, 2718281828, 2718281828}; | |
uint32_t v1[6] = {2718281828, 3141592653, 2718281828, 3141592653, 2718281828, 3141592653}; | |
uint32_t v2[6] = {3141592653, 2718281828, 3141592653, 2718281828, 3141592653, 2718281828}; | |
uint32_t v3[6] = {3141592653, 3141592653, 3141592653, 3141592653, 3141592653, 3141592653}; | |
if (name) { | |
melty2_inject_(v0, name->v[0], name->v[1]); | |
melty2_inject_(v1, name->v[2], name->v[3]); | |
melty2_inject_(v2, name->v[4], name->v[5]); | |
melty2_inject_(v3, name->v[6], name->v[7]); | |
} | |
uint32_t a = v0[0]; | |
uint32_t b = v1[0]; | |
uint32_t c = v2[0]; | |
uint32_t d = v3[0]; | |
melty2_inject_(v0, d, (uint32_t)global_seed); | |
melty2_inject_(v1, a, (uint32_t)global_ctr); | |
melty2_inject_(v2, b, (uint32_t)(global_seed >> 32)); | |
melty2_inject_(v3, c, (uint32_t)(global_ctr >> 32)); | |
melty2_permute_(v0); | |
melty2_permute_(v1); | |
melty2_permute_(v2); | |
melty2_permute_(v3); | |
melty2_permute_(v0); | |
melty2_permute_(v1); | |
melty2_permute_(v2); | |
melty2_permute_(v3); | |
key->v_[0] = v0[0] ^ v1[0] ^ v2[0] ^ v3[0]; | |
key->v_[1] = v0[1] ^ v1[1] ^ v2[1] ^ v3[1]; | |
key->v_[2] = v0[2] ^ v1[2] ^ v2[2] ^ v3[2]; | |
key->v_[3] = v0[3] ^ v1[3] ^ v2[3] ^ v3[3]; | |
key->v_[4] = v0[4] ^ v1[4] ^ v2[4] ^ v3[4]; | |
key->v_[5] = v0[5] ^ v1[5] ^ v2[5] ^ v3[5]; | |
} | |
static inline void melty2_splitkey(melty2_key *key, melty2_key *newkey) { | |
uint32_t v0[6] = {key->v_[0], key->v_[1], key->v_[2], key->v_[3], key->v_[4], key->v_[5]}; | |
uint32_t v1[6] = {key->v_[0], key->v_[1], key->v_[2], key->v_[3], key->v_[4], key->v_[5]}; | |
uint32_t v2[6] = {key->v_[0], key->v_[1], key->v_[2], key->v_[3], key->v_[4], key->v_[5]}; | |
uint32_t v3[6] = {key->v_[0], key->v_[1], key->v_[2], key->v_[3], key->v_[4], key->v_[5]}; | |
melty2_inject_(v0, 2718281828, 0); | |
melty2_inject_(v1, 0, 2718281828); | |
melty2_inject_(v2, 3141592653, 0); | |
melty2_inject_(v3, 0, 3141592653); | |
melty2_permute_(v0); | |
melty2_permute_(v1); | |
melty2_permute_(v2); | |
melty2_permute_(v3); | |
melty2_permute_(v0); | |
melty2_permute_(v1); | |
melty2_permute_(v2); | |
melty2_permute_(v3); | |
uint32_t a = v0[0]; | |
uint32_t b = v1[0]; | |
uint32_t c = v2[0]; | |
uint32_t d = v3[0]; | |
melty2_inject_(v0, d, 0); | |
melty2_inject_(v1, a, 0); | |
melty2_inject_(v2, b, 0); | |
melty2_inject_(v3, c, 0); | |
melty2_permute_(v0); | |
melty2_permute_(v1); | |
melty2_permute_(v2); | |
melty2_permute_(v3); | |
key->v_[0] = v0[0] ^ v2[0]; | |
key->v_[1] = v0[1] ^ v2[1]; | |
key->v_[2] = v0[2] ^ v2[2]; | |
key->v_[3] = v0[3] ^ v2[3]; | |
key->v_[4] = v0[4] ^ v2[4]; | |
key->v_[5] = v0[5] ^ v2[5]; | |
newkey->v_[0] = v1[0] ^ v3[0]; | |
newkey->v_[1] = v1[1] ^ v3[1]; | |
newkey->v_[2] = v1[2] ^ v3[2]; | |
newkey->v_[3] = v1[3] ^ v3[3]; | |
newkey->v_[4] = v1[4] ^ v3[4]; | |
newkey->v_[5] = v1[5] ^ v3[5]; | |
} | |
static uint32_t melty2_gen32(const melty2_key *key, uint64_t idx) { | |
uint32_t v[6] = {key->v_[0], key->v_[1], key->v_[2], key->v_[3], key->v_[4], key->v_[5]}; | |
melty2_inject_(v, (uint32_t)idx, (uint32_t)(idx >> 32)); | |
melty2_permute_(v); | |
return v[0] ^ v[3]; | |
} | |
// | |
// TestU01 | |
uint32_t melty2() { | |
static melty2_key key; | |
static uint64_t idx = 0; | |
static uint32_t buf[4]; | |
static int pos = 0; | |
if (pos == 0) { | |
melty2_initkey(&key, NULL, 0, 0); | |
pos = 4; | |
} | |
if (pos == 4) { | |
pos = 0; | |
// exploit superscalar | |
buf[0] = melty2_gen32(&key, idx++); | |
buf[1] = melty2_gen32(&key, idx++); | |
buf[2] = melty2_gen32(&key, idx++); | |
buf[3] = melty2_gen32(&key, idx++); | |
} | |
uint32_t r = buf[pos++]; | |
#ifdef BITREV | |
uint32_t t; | |
t = r & UINT32_C(0x00FF00FF); | |
r = (t << 16) | (t >> 16) | (t ^ r); | |
t = r & UINT32_C(0x0F0F0F0F); | |
r = (t << 8) | (t >> 24) | (t ^ r); | |
t = r & UINT32_C(0x33333333); | |
r = (t << 4) | (t >> 28) | (t ^ r); | |
t = r & UINT32_C(0x55555555); | |
r = (t << 2) | (t >> 30) | (t ^ r); | |
r = (r << 1) | (r >> 31); | |
#endif | |
return r; | |
} | |
int main() { | |
unif01_Gen *gen; | |
gen = unif01_CreateExternGenBits("melty2", melty2); | |
// bbattery_SmallCrush(gen); | |
// bbattery_Crush(gen); | |
bbattery_BigCrush(gen); | |
unif01_DeleteExternGenBits(gen); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment