xtea.bend
bend-osdev-legacy-ciphers@0.1.0.0 · 69 lines · 9 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import Base
16import bend-osdev-bytes@0.1.0.0/bytes.bend as B
17import bend-osdev-legacy-ciphers@0.1.0.0/legacy_ciphers.bend as L
18import bend-osdev-legacy-ciphers@0.1.0.0/tea.bend as T
19
20
21def xtea.kw(+i: U32, +k0: U32, +k1: U32, +k2: U32, +k3: U32) -> U32:
22 L.lc.at([k0, k1, k2, k3], U32.to_nat(U32.and(3, i)))
23
24
25def xtea.cycles(n: Nat, +s: U32, +k0: U32, +k1: U32, +k2: U32, +k3: U32) -> List<&2, T.LcTeaOp>:
26 match n:
27 case 0n:
28 Nil{}
29 case 1n+p:
30 +s1 = U32.add(s, T.tea.delta())
31 Con{T.LcXteaY{U32.add(s, xtea.kw(s, k0, k1, k2, k3))}, Con{T.LcXteaZ{U32.add(s1, xtea.kw(U32.shrn(s1, 11n), k0, k1, k2, k3))}, xtea.cycles(p, s1, k0, k1, k2, k3)}}
32
33
34type LcXteaKey is Data:
35 LcXteaKey{ops: List<&2, T.LcTeaOp>}
36
37def xtea.key.pick(ok: Bool, +le: Bool, n: Nat, +xs: List<&2, U32>) -> Result<&2, &2, L.LcError, LcXteaKey>:
38 match ok:
39 case True{}:
40 Done{LcXteaKey{T.tea.order(le, xtea.cycles(n, 0, T.tea.word(le, xs, 0n), T.tea.word(le, xs, 4n), T.tea.word(le, xs, 8n), T.tea.word(le, xs, 12n)))}}
41 case False{}:
42 Fail{L.LcBadKeyLength{B.len(xs)}}
43
44
45
46
47
48def LcXtea.key_with(le: Bool, n: Nat, o: B.Octets) -> Result<&2, &2, L.LcError, LcXteaKey>:
49 +xs = B.Octets.to_list(o)
50 xtea.key.pick(Nat.is_eq(B.len(xs), 16n), le, n, xs)
51
52
53
54def LcXtea.key(o: B.Octets) -> Result<&2, &2, L.LcError, LcXteaKey>:
55 LcXtea.key_with(True{}, 32n, o)
56
57
58def LcXtea.key_be(o: B.Octets) -> Result<&2, &2, L.LcError, LcXteaKey>:
59 LcXtea.key_with(False{}, 32n, o)
60
61def LcXtea.encrypt(k: LcXteaKey, b: L.LcBlock64) -> L.LcBlock64:
62 match k:
63 case LcXteaKey{ops}:
64 T.tea.run(ops, b)
65
66def LcXtea.decrypt(k: LcXteaKey, b: L.LcBlock64) -> L.LcBlock64:
67 match k:
68 case LcXteaKey{ops}:
69 T.tea.unrun(ops, b)