4 #define FOR(i,n) for(i=0; i<n; ++i)
7 static int LFSR86540(u8
*R
) { (*R
)=((*R
)<<1)^(((*R
)&0x80)?0x71:0); return ((*R
)&2)>>1; }
8 #define ROL(a,o) ((((u64)a)<<o)^(((u64)a)>>(64-o)))
9 static u64
load64(const u8
*x
) { ui i
; u64 u
=0; FOR(i
,8) { u
<<=8; u
|=x
[7-i
]; } return u
; }
10 static void store64(u8
*x
, u64 u
) { ui i
; FOR(i
,8) { x
[i
]=u
; u
>>=8; } }
11 static void xor64(u8
*x
, u64 u
) { ui i
; FOR(i
,8) { x
[i
]^=u
; u
>>=8; } }
12 #define rL(x,y) load64((u8*)s+8*(x+5*y))
13 #define wL(x,y,l) store64((u8*)s+8*(x+5*y),l)
14 #define XL(x,y,l) xor64((u8*)s+8*(x+5*y),l)
15 static void KeccakF1600(void *s
)
17 ui r
,x
,y
,i
,j
,Y
; u8 R
=0x01; u64 C
[5],D
;
19 /*θ*/ 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
); }
20 /*ρπ*/ 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]; }
21 /*χ*/ 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])); }
22 /*ι*/ FOR(j
,7) if (LFSR86540(&R
)) XL(0,0,(u64
)1<<((1<<j
)-1));
25 void Keccak(u32 r
, u32 c
, const u8
*in
, u64 inLen
, u8 sfx
, u8
*out
, u64 outLen
)
27 /*initialize*/ u8 s
[200]; ui R
=r
/8; ui i
,b
=0; FOR(i
,200) s
[i
]=0;
28 /*absorb*/ while(inLen
>0) { b
=(inLen
<R
)?inLen
:R
; FOR(i
,b
) s
[i
]^=in
[i
]; in
+=b
; inLen
-=b
; if (b
==R
) { KeccakF1600(s
); b
=0; } }
29 /*pad*/ s
[b
]^=sfx
; if((sfx
&0x80)&&(b
==(R
-1))) KeccakF1600(s
); s
[R
-1]^=0x80; KeccakF1600(s
);
30 /*squeeze*/ while(outLen
>0) { b
=(outLen
<R
)?outLen
:R
; FOR(i
,b
) out
[i
]=s
[i
]; out
+=b
; outLen
-=b
; if(outLen
>0) KeccakF1600(s
); }