-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGimli.bsv
96 lines (80 loc) · 2.93 KB
/
Gimli.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
package Gimli;
import InputLayer :: *;
import OutputLayer :: *;
import GimliCipher :: *;
import CryptoCore :: *;
typedef enum {
InIdle, // waiting on process command
InBusy // recieve from bdi
} InputState deriving(Bits, Eq);
module mkGimli(CryptoCoreIfc);
let cipher <- mkGimliCipher;
Byte padByte = 8'b1;
let inLayer <- mkInputLayer(padByte);
let outLayer <- mkOutputLayer;
let inState <- mkReg(InIdle);
let set_busy <- mkPulseWire;
let set_idle <- mkPulseWire;
Reg#(Bool) isKey <- mkRegU;
Reg#(Bool) isHM <- mkRegU;
Reg#(Bool) isCT <- mkRegU;
Reg#(Bool) isPTCT <- mkRegU; // PT or CT
Reg#(Bool) isNpub <- mkRegU;
Reg#(Bool) isAD <- mkRegU;
Reg#(Bool) first <- mkRegU;
Reg#(Bool) last <- mkRegU;
// ==================================================== Rules =====================================================
(* fire_when_enabled *)
rule rl_change_state if (set_busy || set_idle);
if (set_busy)
inState <= InBusy;
else if (set_idle)
inState <= InIdle;
endrule
(* fire_when_enabled *)
rule rl_encipher if (inState == InBusy);
match {.inBlock, .valids} <- inLayer.get;
let last_block = last && !inLayer.extraPad;
let outBlock <- cipher.blockUp(inBlock, valids, Flags {key:isKey, ct:isCT, ad:isAD, npub:isNpub, hash:isHM, first:first, last:last_block});
if (isPTCT) outLayer.enq(outBlock, valids);
if (last_block) set_idle.send;
first <= False;
endrule
(* fire_when_enabled *)
rule rl_squeeze_tag_or_digest;
let out <- cipher.blockDown;
outLayer.enq(out, replicate(True));
endrule
// ================================================== Interfaces ==================================================
method Action init(OpCode op) if (inState == InIdle);
cipher.init(op);
endmethod
method Action process(SegmentType typ, Bool empty, Bool eoi) if (inState == InIdle);
// only AD, CT, PT, HM can be empty
if (empty)
inLayer.put(unpack(zeroExtend(padByte)), True, False, 0, True);
set_busy.send;
first <= True;
last <= empty;
isKey <= typ == Key;
isNpub <= typ == Npub;
isHM <= typ == HashMessage;
isCT <= typ == Ciphertext;
isAD <= typ == AD;
isPTCT <= typ == Ciphertext || typ == Plaintext;
endmethod
interface FifoIn bdi;
method Action enq(i) if (inState == InBusy);
inLayer.put(unpack(pack(i.word)), i.lot, i.lot && !isKey && !isNpub, i.padarg, False);
last <= i.lot;
endmethod
endinterface
interface FifoOut bdo;
method deq = outLayer.deq;
method first;
return BdIO {word: outLayer.first, lot: outLayer.isLast, padarg: 0};
endmethod
method notEmpty = outLayer.notEmpty;
endinterface
endmodule : mkGimli
endpackage : Gimli