rc4.bend
bend-osdev-legacy-ciphers@0.1.0.0 · 211 lines · 28 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import Base
17import bend-osdev-bytes@0.1.0.0/bytes.bend as B
18import bend-osdev-legacy-ciphers@0.1.0.0/legacy_ciphers.bend as L
19
20
21
22
23def rc4.path(d: Nat, +i: U32) -> List<&2, Bool>:
24 match d:
25 case 0n:
26 Nil{}
27 case 1n+(+p):
28 Con{U32.is_eq(L.lc.bit(i, p), 1), rc4.path(p, i)}
29
30def rc4.get(t: L.LcTab, path: List<&2, Bool>) -> U32:
31 match t:
32 case L.LcLeaf{v}:
33 v
34 case L.LcNode{l, r}:
35 match path:
36 case Nil{}:
37 0
38 case Con{b, rest}:
39 match b:
40 case True{}:
41 rc4.get(r, rest)
42 case False{}:
43 rc4.get(l, rest)
44
45def rc4.set(t: L.LcTab, path: List<&2, Bool>, v: U32) -> L.LcTab:
46 match t:
47 case L.LcLeaf{w}:
48 L.LcLeaf{v}
49 case L.LcNode{l, r}:
50 match path:
51 case Nil{}:
52 L.LcNode{l, r}
53 case Con{b, rest}:
54 match b:
55 case True{}:
56 L.LcNode{l, rc4.set(r, rest, v)}
57 case False{}:
58 L.LcNode{rc4.set(l, rest, v), r}
59
60def rc4.at(+s: L.LcTab, +i: U32) -> U32:
61 rc4.get(s, rc4.path(8n, i))
62
63
64def rc4.swap(+s: L.LcTab, +i: U32, +j: U32) -> L.LcTab:
65 +a = rc4.at(s, i)
66 +b = rc4.at(s, j)
67 rc4.set(rc4.set(s, rc4.path(8n, i), b), rc4.path(8n, j), a)
68
69
70def rc4.ident(n: Nat, +i: U32) -> List<&2, U32>:
71 match n:
72 case 0n:
73 Nil{}
74 case 1n+p:
75 Con{i, rc4.ident(p, U32.add(i, 1))}
76
77
78type LcRc4State is Data:
79 LcRc4State{s: L.LcTab, i: U32, j: U32}
80
81
82
83def rc4.ksa(n: Nat, +key: List<&2, U32>, +klen: Nat, +s: L.LcTab, +i: U32, +j: U32) -> L.LcTab:
84 match n:
85 case 0n:
86 s
87 case 1n+p:
88 +j2 = U32.and(255, U32.add(U32.add(j, rc4.at(s, i)), L.lc.at(key, Nat.mod(U32.to_nat(i), klen))))
89 rc4.ksa(p, key, klen, rc4.swap(s, i, j2), U32.add(i, 1), j2)
90
91
92type LcRc4Step is Data:
93 LcRc4Step{st: LcRc4State, k: U32}
94
95
96def rc4.next(st: LcRc4State) -> LcRc4Step:
97 match st:
98 case LcRc4State{+s, i, j}:
99 +i2 = U32.and(255, U32.add(i, 1))
100 +j2 = U32.and(255, U32.add(j, rc4.at(s, i2)))
101 +s2 = rc4.swap(s, i2, j2)
102 LcRc4Step{LcRc4State{s2, i2, j2}, rc4.at(s2, U32.and(255, U32.add(rc4.at(s2, i2), rc4.at(s2, j2))))}
103
104def rc4.step.st(r: LcRc4Step) -> LcRc4State:
105 match r:
106 case LcRc4Step{st, k}:
107 st
108
109def rc4.step.k(r: LcRc4Step) -> U32:
110 match r:
111 case LcRc4Step{st, k}:
112 k
113
114
115
116
117def rc4.xs(xs: List<&2, U32>, st: LcRc4State) -> List<&2, U32>:
118 match xs:
119 case Nil{}:
120 Nil{}
121 case Con{x, t}:
122 +n = rc4.next(st)
123 Con{B.byte(U32.xor(x, rc4.step.k(n))), rc4.xs(t, rc4.step.st(n))}
124
125def rc4.after(xs: List<&2, U32>, st: LcRc4State) -> LcRc4State:
126 match xs:
127 case Nil{}:
128 st
129 case Con{x, t}:
130 rc4.after(t, rc4.step.st(rc4.next(st)))
131
132
133
134type LcRc4Out is Data:
135 LcRc4Out{state: LcRc4State, data: B.Octets}
136
137
138
139
140def rc4.rev_onto(xs: List<&2, U32>, acc: List<&2, U32>) -> List<&2, U32>:
141 match xs:
142 case Nil{}:
143 acc
144 case Con{h, t}:
145 rc4.rev_onto(t, Con{h, acc})
146
147type LcRc4Run is Data:
148 LcRc4Run{st: LcRc4State, out: List<&2, U32>}
149
150def rc4.go(xs: List<&2, U32>, st: LcRc4State, acc: List<&2, U32>) -> LcRc4Run:
151 match xs:
152 case Nil{}:
153 LcRc4Run{st, rc4.rev_onto(acc, Nil{})}
154 case Con{x, t}:
155 +n = rc4.next(st)
156 rc4.go(t, rc4.step.st(n), Con{B.byte(U32.xor(x, rc4.step.k(n))), acc})
157
158def rc4.out(r: LcRc4Run) -> LcRc4Out:
159 match r:
160 case LcRc4Run{st, out}:
161 LcRc4Out{st, B.Octets.of_list(out)}
162
163
164def rc4.drop(n: Nat, st: LcRc4State) -> LcRc4State:
165 match n:
166 case 0n:
167 st
168 case 1n+p:
169 rc4.drop(p, rc4.step.st(rc4.next(st)))
170
171def rc4.start.pick(ok: Bool, +key: List<&2, U32>, +klen: Nat) -> Result<&2, &2, L.LcError, LcRc4State>:
172 match ok:
173 case True{}:
174 Done{LcRc4State{rc4.ksa(256n, key, klen, L.lc.tab(8n, rc4.ident(256n, 0)), 0, 0), 0, 0}}
175 case False{}:
176 Fail{L.LcBadKeyLength{klen}}
177
178
179
180
181def LcRc4.start(key: B.Octets) -> Result<&2, &2, L.LcError, LcRc4State>:
182 +xs = B.Octets.to_list(key)
183 +n = B.len(xs)
184 rc4.start.pick(Bool.and(Nat.is_lt(0n, n), Nat.is_le(n, 256n)), xs, n)
185
186
187
188def LcRc4.start_drop(key: B.Octets, n: Nat) -> Result<&2, &2, L.LcError, LcRc4State>:
189 Result.map(&2, &2, L.LcError, LcRc4State, LcRc4State, st => rc4.drop(n, st), LcRc4.start(key))
190
191
192def LcRc4.update(st: LcRc4State, m: B.Octets) -> LcRc4Out:
193 rc4.out(rc4.go(B.Octets.to_list(m), st, Nil{}))
194
195def LcRc4.out_state(o: LcRc4Out) -> LcRc4State:
196 match o:
197 case LcRc4Out{st, d}:
198 st
199
200def LcRc4.out_data(o: LcRc4Out) -> B.Octets:
201 match o:
202 case LcRc4Out{st, d}:
203 d
204
205
206def LcRc4.crypt(key: B.Octets, m: B.Octets) -> Result<&2, &2, L.LcError, B.Octets>:
207 Result.map(&2, &2, L.LcError, LcRc4State, B.Octets, st => LcRc4.out_data(LcRc4.update(st, m)), LcRc4.start(key))
208
209
210def LcRc4.keystream(st: LcRc4State, n: Nat) -> LcRc4Out:
211 LcRc4.update(st, B.Octets.zeros(n))