gf128.bend
bend-osdev-gf@0.1.1.0 · 172 lines · 29 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import Base
20import bend-osdev-bytes@0.1.1.0/bytes.bend as B
21
22type Gf128 is Data:
23 Gf128{w0: U32, w1: U32, w2: U32, w3: U32}
24
25type Gf128Error is Data:
26 Gf128BadLength{got: Nat}
27
28def Gf128.zero() -> Gf128:
29 Gf128{0, 0, 0, 0}
30
31def Gf128.of_words(w0: U32, w1: U32, w2: U32, w3: U32) -> Gf128:
32 Gf128{w0, w1, w2, w3}
33
34def Gf128.words(x: Gf128) -> List<&2, U32>:
35 match x:
36 case Gf128{w0, w1, w2, w3}:
37 [w0, w1, w2, w3]
38
39def Gf128.xor(a: Gf128, b: Gf128) -> Gf128:
40 match a b:
41 case Gf128{a0, a1, a2, a3} Gf128{b0, b1, b2, b3}:
42 Gf128{U32.xor(a0, b0), U32.xor(a1, b1), U32.xor(a2, b2), U32.xor(a3, b3)}
43
44def Gf128.is_eq(a: Gf128, b: Gf128) -> Bool:
45 match a b:
46 case Gf128{a0, a1, a2, a3} Gf128{b0, b1, b2, b3}:
47 Bool.and(U32.is_eq(a0, b0), Bool.and(U32.is_eq(a1, b1), Bool.and(U32.is_eq(a2, b2), U32.is_eq(a3, b3))))
48
49
50
51def gf128.word(a: U32, b: U32, c: U32, d: U32) -> U32:
52 U32.or(U32.shln(U32.and(255, a), 24n), U32.or(U32.shln(U32.and(255, b), 16n), U32.or(U32.shln(U32.and(255, c), 8n), U32.and(255, d))))
53
54def gf128.of_list.go(xs: List<&2, U32>) -> Gf128:
55 match xs:
56 case Con{a0, Con{a1, Con{a2, Con{a3, Con{a4, Con{a5, Con{a6, Con{a7, Con{a8, Con{a9, Con{a10, Con{a11, Con{a12, Con{a13, Con{a14, Con{a15, t}}}}}}}}}}}}}}}}:
57 Gf128{gf128.word(a0, a1, a2, a3), gf128.word(a4, a5, a6, a7), gf128.word(a8, a9, a10, a11), gf128.word(a12, a13, a14, a15)}
58 case o:
59 Gf128.zero()
60
61def gf128.of_list.pick(ok: Bool, +n: Nat, +xs: List<&2, U32>) -> Result<&2, &2, Gf128Error, Gf128>:
62 match ok:
63 case True{}:
64 Done{gf128.of_list.go(xs)}
65 case False{}:
66 Fail{Gf128BadLength{n}}
67
68
69def Gf128.of_octets(+o: B.Octets) -> Result<&2, &2, Gf128Error, Gf128>:
70 +n = B.Octets.len(o)
71 gf128.of_list.pick(Nat.is_eq(n, 16n), n, B.Octets.to_list(o))
72
73def Gf128.to_octets(x: Gf128) -> B.Octets:
74 match x:
75 case Gf128{w0, w1, w2, w3}:
76 B.Octets.concat([B.Octets.be32(w0), B.Octets.be32(w1), B.Octets.be32(w2), B.Octets.be32(w3)])
77
78def Gf128.hex(x: Gf128) -> String:
79 B.Octets.hex(Gf128.to_octets(x))
80
81
82def gf128.mask(b: U32) -> U32:
83 U32.sub(0, U32.and(b, 1))
84
85def Gf128.and_mask(a: Gf128, +m: U32) -> Gf128:
86 match a:
87 case Gf128{w0, w1, w2, w3}:
88 Gf128{U32.and(w0, m), U32.and(w1, m), U32.and(w2, m), U32.and(w3, m)}
89
90
91
92
93def Gf128.mul_x_gcm(v: Gf128) -> Gf128:
94 match v:
95 case Gf128{+w0, +w1, +w2, +w3}:
96 Gf128{U32.xor(U32.shr(w0), U32.and(3774873600, gf128.mask(w3))), U32.or(U32.shr(w1), U32.shln(w0, 31n)), U32.or(U32.shr(w2), U32.shln(w1, 31n)), U32.or(U32.shr(w3), U32.shln(w2, 31n))}
97
98
99
100def Gf128.double_be(v: Gf128) -> Gf128:
101 match v:
102 case Gf128{+w0, +w1, +w2, +w3}:
103 Gf128{U32.or(U32.shl(w0), U32.shrn(w1, 31n)), U32.or(U32.shl(w1), U32.shrn(w2, 31n)), U32.or(U32.shl(w2), U32.shrn(w3, 31n)), U32.xor(U32.shl(w3), U32.and(135, gf128.mask(U32.shrn(w0, 31n))))}
104
105
106
107
108
109def gf128.le.shift(+w: U32) -> U32:
110 U32.or(U32.and(4278124286, U32.shl(w)), U32.and(65793, U32.shrn(w, 15n)))
111
112
113def gf128.le.carry(w: U32) -> U32:
114 U32.shln(U32.and(128, w), 17n)
115
116def Gf128.double_le(v: Gf128) -> Gf128:
117 match v:
118 case Gf128{+w0, +w1, +w2, +w3}:
119 Gf128{U32.xor(gf128.le.shift(w0), U32.and(2264924160, gf128.mask(U32.shrn(w3, 7n)))), U32.or(gf128.le.shift(w1), gf128.le.carry(w0)), U32.or(gf128.le.shift(w2), gf128.le.carry(w1)), U32.or(gf128.le.shift(w3), gf128.le.carry(w2))}
120
121
122
123
124def gf128.gcm.bit(+x: U32, zv: Gf128 & Gf128) -> Gf128 & Gf128:
125 (z, +v) = zv
126 (Gf128.xor(z, Gf128.and_mask(v, gf128.mask(U32.shrn(x, 31n)))), Gf128.mul_x_gcm(v))
127
128
129def gf128.gcm.word(n: Nat, +x: U32, zv: Gf128 & Gf128) -> Gf128 & Gf128:
130 match n:
131 case 0n:
132 zv
133 case 1n+k:
134 gf128.gcm.word(k, U32.shl(x), gf128.gcm.bit(x, zv))
135
136def gf128.fst(p: Gf128 & Gf128) -> Gf128:
137 (a, b) = p
138 a
139
140def Gf128.mul_gcm(x: Gf128, y: Gf128) -> Gf128:
141 match x:
142 case Gf128{w0, w1, w2, w3}:
143 gf128.fst(gf128.gcm.word(32n, w3, gf128.gcm.word(32n, w2, gf128.gcm.word(32n, w1, gf128.gcm.word(32n, w0, (Gf128.zero(), y))))))
144
145
146def Gf128.ghash_update(+h: Gf128, y: Gf128, x: Gf128) -> Gf128:
147 Gf128.mul_gcm(Gf128.xor(y, x), h)
148
149def Gf128.ghash.go(xs: List<&2, Gf128>, +h: Gf128, y: Gf128) -> Gf128:
150 match xs:
151 case Nil{}:
152 y
153 case Con{x, rest}:
154 Gf128.ghash.go(rest, h, Gf128.ghash_update(h, y, x))
155
156def Gf128.ghash(+h: Gf128, xs: List<&2, Gf128>) -> Gf128:
157 Gf128.ghash.go(xs, h, Gf128.zero())
158
159
160
161
162def gf128.be.word(n: Nat, +x: U32, +a: Gf128, z: Gf128) -> Gf128:
163 match n:
164 case 0n:
165 z
166 case 1n+k:
167 gf128.be.word(k, U32.shl(x), a, Gf128.xor(Gf128.double_be(z), Gf128.and_mask(a, gf128.mask(U32.shrn(x, 31n)))))
168
169def Gf128.mul_be(+a: Gf128, b: Gf128) -> Gf128:
170 match b:
171 case Gf128{w0, w1, w2, w3}:
172 gf128.be.word(32n, w3, a, gf128.be.word(32n, w2, a, gf128.be.word(32n, w1, a, gf128.be.word(32n, w0, a, Gf128.zero()))))