#if defined(DQN_KECCAK_H) // ----------------------------------------------------------------------------- // Dqn_Keccak Reference Implementation // ----------------------------------------------------------------------------- // A very compact Keccak implementation taken from the reference implementation // repository // // https://github.com/XKCP/XKCP/blob/master/Standalone/CompactFIPS202/C/Keccak-more-compact.c // #define FOR(i,n) for(i=0; i>1; } #define ROL(a,o) ((((u64)a)<>(64-o))) static u64 load64(const u8 *x) { ui i; u64 u=0; FOR(i,8) { u<<=8; u|=x[7-i]; } return u; } static void store64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]=u; u>>=8; } } static void xor64(u8 *x, u64 u) { ui i; FOR(i,8) { x[i]^=u; u>>=8; } } #define rL(x,y) load64((u8*)s+8*(x+5*y)) #define wL(x,y,l) store64((u8*)s+8*(x+5*y),l) #define XL(x,y,l) xor64((u8*)s+8*(x+5*y),l) void KeccakF1600(void *s) { ui r,x,y,i,j,Y; u8 R=0x01; u64 C[5],D; for(i=0; i<24; i++) { /*θ*/ FOR(x,5) C[x]=rL(x,0)^rL(x,1)^rL(x,2)^rL(x,3)^rL(x,4); FOR(x,5) { D=C[(x+4)%5]^ROL(C[(x+1)%5],1); FOR(y,5) XL(x,y,D); } /*ρπ*/ x=1; y=r=0; D=rL(x,y); FOR(j,24) { r+=j+1; Y=(2*x+3*y)%5; x=y; y=Y; C[0]=rL(x,y); wL(x,y,ROL(D,r%64)); D=C[0]; } /*χ*/ FOR(y,5) { FOR(x,5) C[x]=rL(x,y); FOR(x,5) wL(x,y,C[x]^((~C[(x+1)%5])&C[(x+2)%5])); } /*ι*/ FOR(j,7) if (LFSR86540(&R)) XL(0,0,(u64)1<<((1<0) { b=(inLen0) { b=(outLen0) KeccakF1600(s); } } // PCG32 Random Number Generator // ----------------------------------------------------------------------------- // NOTE: https://github.com/imneme/pcg-c-basic struct pcg_state_setseq_64 { // Internals are *Private*. uint64_t state; // RNG state. All values are possible. uint64_t inc; // Controls which RNG sequence (stream) is // selected. Must *always* be odd. }; typedef struct pcg_state_setseq_64 pcg32_random_t; // pcg32_random_r(rng) // Generate a uniformly distributed 32-bit random number uint32_t pcg32_random_r(pcg32_random_t* rng) { uint64_t oldstate = rng->state; rng->state = oldstate * 6364136223846793005ULL + rng->inc; uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; uint32_t rot = oldstate >> 59u; return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); } // pcg32_srandom_r(rng, initstate, initseq): // Seed the rng. Specified in two parts, state initializer and a // sequence selection constant (a.k.a. stream id) void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initstate, uint64_t initseq) { rng->state = 0U; rng->inc = (initseq << 1u) | 1u; pcg32_random_r(rng); rng->state += initstate; pcg32_random_r(rng); } // pcg32_boundedrand_r(rng, bound): // Generate a uniformly distributed number, r, where 0 <= r < bound uint32_t pcg32_boundedrand_r(pcg32_random_t* rng, uint32_t bound) { uint32_t threshold = -bound % bound; for (;;) { uint32_t r = pcg32_random_r(rng); if (r >= threshold) return r % bound; } } #endif // DQN_KECCAK_H