2 | module Crypto.Hash.Poly1305
11 | record Poly1305 where
12 | constructor MkPoly1305
18 | record Bits128 where
19 | constructor MkBits128
23 | mask_low_2_bits : Bits64
24 | mask_low_2_bits = 0x0000000000000003
26 | mask_not_low_2_bits : Bits64
27 | mask_not_low_2_bits = complement mask_low_2_bits
30 | p0 = 0xFFFFFFFFFFFFFFFB
33 | p1 = 0xFFFFFFFFFFFFFFFF
36 | p2 = 0x0000000000000003
38 | add64 : Bits64 -> Bits64 -> Bits64 -> (Bits64, Bits64)
40 | let sum = x + y + carry
41 | carry = shiftR ((x .&. y) .|. ((x .|. y) .&. (complement sum))) 63
44 | sub64 : Bits64 -> Bits64 -> Bits64 -> (Bits64, Bits64)
46 | let diff = x - y - borrow
47 | borrow_out = shiftR ((complement x .&. y) .|. (diff .&. complement (x `xor` y))) 63
48 | in (diff, borrow_out)
50 | mul64_mask32 : Bits64
51 | mul64_mask32 = cast (the Bits32 oneBits)
53 | mul64 : Bits64 -> Bits64 -> Bits128
55 | let x0 = x .&. mul64_mask32
57 | y0 = y .&. mul64_mask32
60 | t = (x1 * y0) + (shiftR w0 32)
61 | w1 = t .&. mul64_mask32
64 | in MkBits128 (x * y) (x1 * y1 + w2 + (shiftR w1 32))
66 | add128 : Bits128 -> Bits128 -> Bits128
68 | let (lo, c) = add64 a.lo b.lo 0
69 | (hi, _) = add64 a.hi b.hi c
72 | shiftr2 : Bits128 -> Bits128
73 | shiftr2 a = MkBits128 ((shiftR a.lo 2) .|. (shiftL (a.hi .&. 3) 62)) (shiftR a.hi 2)
76 | select64 : Bits64 -> Bits64 -> Bits64 -> Bits64
77 | select64 v x y = (x .&. complement (v - 1)) .|. (y .&. (v - 1))
79 | core : Poly1305 -> Bits64 -> Bits64 -> Bits64 -> (Bits64, Bits64, Bits64)
80 | core state h0 h1 h2 =
81 | let [r0, r1] = state.r
91 | m1 = add128 h1r0 h0r1
92 | m2 = add128 h2r0 h1r1
96 | (t1, c) = add64 m1.lo m0.hi 0
97 | (t2, c) = add64 m2.lo m1.hi c
98 | (t3, _) = add64 m3.lo m2.hi c
102 | h2 = t2 .&. mask_low_2_bits
103 | cc = MkBits128 (t2 .&. mask_not_low_2_bits) t3
105 | (h0, c) = add64 h0 cc.lo 0
106 | (h1, c) = add64 h1 cc.hi c
111 | (h0, c) = add64 h0 cc.lo 0
112 | (h1, c) = add64 h1 cc.hi c
116 | update' : Poly1305 -> Poly1305
118 | case splitAtExact 16 state.buffer of
119 | Just (buf, rest) =>
120 | let (a, b) = bimap from_le from_le (splitAt 8 buf)
121 | [h0, h1, h2] = state.h
122 | (h0, c) = add64 h0 a 0
123 | (h1, c) = add64 h1 b c
125 | (h0, h1, h2) = core state h0 h1 h2
126 | in {h := [h0, h1, h2]} state
129 | finalize' : Poly1305 -> Vect 16 Bits8
131 | case exactLength 16 (fromList state.buffer) of
133 | let (a, b) = bimap from_le from_le (splitAt 8 buf)
134 | [h0, h1, h2] = state.h
135 | (h0, c) = add64 h0 a 0
136 | (h1, c) = add64 h1 b c
138 | (h0, h1, h2) = core state h0 h1 h2
140 | (t0, b) = sub64 h0 p0 0
141 | (t1, b) = sub64 h1 p1 b
142 | (_ , b) = sub64 h2 p2 b
144 | h0 = select64 b h0 t0
145 | h1 = select64 b h1 t1
148 | (h0, c) = add64 h0 s0 0
149 | (h1, _) = add64 h1 s1 c
150 | in to_le {n=8} h0 ++ to_le {n=8} h1
152 | finalize' $
{ buffer := pad_zero 16 (state.buffer <+> [ 0x01 ]) } (update' state)
155 | Digest Poly1305 where
157 | update message state = update' $
{buffer := state.buffer <+> message} state
158 | finalize = finalize'
161 | MAC (Vect 32 Bits8) Poly1305 where
162 | initialize_mac key =
163 | let ([r0, r1], s) = splitAt 2 $
map from_le $
group 4 8 key
164 | r0 = r0 .&. 0x0FFFFFFC0FFFFFFF
165 | r1 = r1 .&. 0x0FFFFFFC0FFFFFFC
166 | in MkPoly1305 [] [0,0,0] [r0, r1] s