Grain Stream Cipher
From Gezel2
This is the Grain Stream Cipher (grain v1 to be exact). See [http://www.it.lth.se/grain/].
I am curious why proposers of HARDWARE crypto algorithms tend to provide reference implementations in SOFTWARE. This applies not just to grain, but to virtually every hash, secret-key and public-key design proposed in the past few years (e.g. check [ESTREAM]). As you can see from the code below, an RTL reference implementation really takes no more than a single page of code.
[edit] grain.fdl
dp grain(in init : ns(1);
in run : ns(1);
in key : ns(80);
in iv : ns(64);
out z : ns(1);
out valid : ns(1)) {
reg n, l : ns(80); // n = NFSR state, l = LFSR state
reg cnt : ns(8); // count init cycles (160 downto 0)
reg val : ns(1);
sig nxt_n, nxt_l : ns(80);
sig go : ns(1);
sig g, f, h, l_bit, n_bit : ns(1);
sig x0, x1, x2, x3, x4 : ns(1);
always {
n = init ? key : nxt_n;
l = init ? ((ns(16)) 0xffff) # iv : nxt_l;
val = init ? 0 : (cnt == 1) ? 1 : val;
valid = val;
cnt = init ? 160 : (cnt ? cnt - 1 : 0);
go = (cnt != 0) | run;
f = l[0] ^ l[13] ^ l[23] ^ l[38] ^ l[51] ^ l[62];
g = l[ 0] ^ n[62] ^ n[60] ^ n[52] ^ n[45] ^
n[37] ^ n[33] ^ n[28] ^ n[21] ^
n[14] ^ n[ 9] ^ n[ 0] ^
(n[63] & n[60]) ^
(n[37] & n[33]) ^
(n[15] & n[9]) ^
(n[60] & n[52] & n[45]) ^
(n[33] & n[28] & n[21]) ^
(n[63] & n[45] & n[28] & n[ 9]) ^
(n[60] & n[52] & n[37] & n[33]) ^
(n[63] & n[60] & n[21] & n[15]) ^
(n[63] & n[60] & n[52] & n[45] & n[37]) ^
(n[33] & n[28] & n[21] & n[15] & n[ 9]) ^
(n[52] & n[45] & n[37] & n[33] & n[28] & n[21]);
x0 = l[ 3];
x1 = l[25];
x2 = l[46];
x3 = l[64];
x4 = n[63];
h = x1 ^ x4 ^ (x0 & x3) ^ (x2 & x3) ^
(x3 & x4) ^ (x0 & x1 & x2) ^ (x0 & x2 & x3) ^
(x0 & x2 & x4) ^ (x1 & x2 & x4) ^ (x2 & x3 & x4);
l_bit = (cnt != 0) ? (f ^ z) : f;
n_bit = (cnt != 0) ? (g ^ z) : g;
nxt_l = go ? l_bit # l[79:1] : l;
nxt_n = go ? n_bit # n[79:1] : n;
z = h ^ n[1] ^ n[2] ^ n[4] ^ n[10] ^ n[31] ^ n[43] ^ n[56];
}
}
dp testgrain {
sig init : ns(1);
sig run : ns(1);
sig key : ns(80);
sig iv : ns(64);
sig z : ns(1);
sig v : ns(1);
reg zw : ns(8);
reg c : ns(3);
reg zr : ns(1);
reg vr : ns(1);
sig zws : ns(8);
use grain(init, run, key, iv, z, v);
sfg load {
init = 1;
run = 0;
key = 0;
iv = 0;
}
sfg nokey {
key = 0;
iv = 0;
init = 0;
run = 1;
}
sfg wait {
zr = z;
vr = v;
}
sfg collect {
zw = zr # zw[7:1];
c = c + 1;
zr = z;
key = 0;
iv = 0;
init = 0;
run = 1;
zws = zw;
}
sfg show {
$display("C ", $cycle, " -> ", zws);
}
}
fsm ctl(testgrain) {
initial s0;
state s1, s2;
@s0 (load, wait) -> s1;
@s1 if (vr) then (collect) -> s2;
else (wait, nokey) -> s1;
@s2 if (c==0) then (collect, show) -> s2;
else (collect) -> s2;
}
system S {
testgrain;
}
[edit] Simulation Output
# fdlsim grain.fdl 300 C 170 -> de C 178 -> e9 C 186 -> 31 C 194 -> cf C 202 -> 16 C 210 -> 62 C 218 -> a7 C 226 -> 2f C 234 -> 77 C 242 -> d0 C 250 -> 2b C 258 -> 6b C 266 -> 61 C 274 -> 88 C 282 -> a8 C 290 -> f6 C 298 -> a2
