-
Notifications
You must be signed in to change notification settings - Fork 1
/
GiftCipher.bsv
106 lines (89 loc) · 3.05 KB
/
GiftCipher.bsv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package GiftCipher;
import Vector :: *;
import Printf :: *;
import BluelightUtils :: *;
import GiftRound :: *;
import Probe :: *;
export Vector :: *;
export GiftCipher :: *;
export BluelightUtils :: *;
typedef 40 CipherRounds;
// 1, 2, 4, 5, 8, 10, 20, 40
typedef 5 UnrollFactor;
typedef BlockOfSize#(GiftBlockBytes) Block;
typedef Vector#(GiftBlockBytes, Bool) ByteValids;
typedef BlockOfSize#(TDiv#(GiftBlockBytes,2)) HalfBlock;
function HalfBlock double(HalfBlock s);
HalfBlock tmp;
/*x^{64} + x^4 + x^3 + x + 1*/
for (Integer i = 0; i < 8; i = i + 1)
tmp[i] = {s[i][6:0], s[(i+1) % 8][7]};
let b = s[0][7];
tmp[7][1] = tmp[7][1] ^ b;
tmp[7][3] = tmp[7][3] ^ b;
tmp[7][4] = tmp[7][4] ^ b;
return tmp;
endfunction
function HalfBlock triple(HalfBlock s);
return unpack(pack(double(s)) ^ pack(s));
endfunction
function GiftState toGiftState(Block block);
GiftState s;
for (Integer i = 0; i < valueOf(NumBlockWords); i = i + 1)
s[i] = swapEndian(takeAt(4*i, block));
return s;
endfunction
function KeyState toKeyState(Block block);
KeyState s = unpack(pack(block));
return map(swapEndian, s);
endfunction
function KeyState restore_keystate(KeyState nextKS);
KeyState swapped_ks = newVector;
for (Integer i = 0; i < 8; i = i + 1)
swapped_ks[i] = swapEndian(i % 2 == 0 ? rotateRight(nextKS[i], 4'b0) : nextKS[i]);
return swapped_ks;
endfunction
function Block giftStateToBlock(GiftState s);
// big-endian
s = map(swapEndian, s);
return unpack(pack(s));
endfunction
// Y[1],Y[2] -> Y[2],Y[1]<<<1
function Block gee(Block s);
Block tmp = newVector;
for (Integer i = 0; i < 8; i = i + 1) begin
tmp[i] = s[8+i];
tmp[i+8] = {s[i][6:0], s[(i+1) % 8][7]};
end
return tmp;
endfunction
function Byte en_byte_xor(Byte b, Bool v, Byte c);
return (v ? b : 0) ^ c;
endfunction
// TODO optimize?
function Tuple2#(Block, Block) pho(Block y, Block m, ByteValids valids, Bool ct);
Block c = zipWith3(en_byte_xor, y, valids, m);
// X[i] = (pad(A[i]) + G(Y[i-1])) + offset
Block x = unpack(pack(gee(y)) ^ pack(ct ? c : m));
return tuple2(x, c);
endfunction
function Tuple3#(GiftState,KeyState,RoundConstant) giftRound(GiftState s, KeyState w, RoundConstant rc);
Tuple3#(GiftState,KeyState,RoundConstant) x = tuple3(s,w,rc);
for (Integer i = 0; i < valueOf(UnrollFactor); i = i + 1)
x = singleRound(tpl_1(x), tpl_2(x), tpl_3(x));
return x;
endfunction
function GiftState xor_topbar_block(Block s1, HalfBlock s2);
Block tmp = s1;
for (Integer i = 0; i < 8; i = i + 1)
tmp[i] = s1[i] ^ s2[i];
return toGiftState(tmp);
endfunction
function HalfBlock gen_offset(Block y, HalfBlock delta, Bool isFirstAD, Bool fullBlockMsgNotEmpty, Bool isLastBlock);
let delta1 = isFirstAD ? take(y) : delta;
HalfBlock offsetX2 = double(delta1);
let offsetX3 = unpack(pack(offsetX2) ^ pack(delta1));
let offsetX9 = triple(offsetX3);
return isLastBlock ? (fullBlockMsgNotEmpty ? offsetX3 : offsetX9) : offsetX2;
endfunction
endpackage