hmac.bend
bend-osdev-crypto@0.1.0.0 · 80 lines · 12 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-crypto@0.1.0.0/crypto.bend as Cr
18import bend-osdev-crypto@0.1.0.0/mac.bend as Mc
19
20
21type CrHmacKey is Data:
22 CrHmacKey{ipad: B.Octets, opad: B.Octets}
23
24
25type CrHmacState<-H: Data> is Data:
26 CrHmacState{inner: H, opad: B.Octets}
27
28def cr.hmac.pad(xs: List<&2, U32>, +c: U32) -> List<&2, U32>:
29 match xs:
30 case Nil{}:
31 Nil{}
32 case Con{x, t}:
33 Con{B.byte(U32.xor(x, c)), cr.hmac.pad(t, c)}
34
35def cr.hmac.k0(~digest: B.Octets -> B.Octets, long: Bool, +key: B.Octets) -> B.Octets:
36 match long:
37 case True{}:
38 digest(key)
39 case False{}:
40 key
41
42
43def cr.hmac.block(~bsize: Nat, ~digest: B.Octets -> B.Octets, +key: B.Octets) -> List<&2, U32>:
44 +k = cr.hmac.k0(~digest, Nat.is_lt(bsize, B.Octets.len(key)), key)
45 B.append(B.Octets.to_list(k), B.zeros(Nat.sub(bsize, B.Octets.len(k))))
46
47
48def CrHmac.key(~bsize: Nat, ~digest: B.Octets -> B.Octets, key: B.Octets) -> CrHmacKey:
49 +k0 = cr.hmac.block(~bsize, ~digest, key)
50 CrHmacKey{B.Octets.of_list(cr.hmac.pad(k0, 54)), B.Octets.of_list(cr.hmac.pad(k0, 92))}
51
52
53def CrHmac.key_of(~bsize: Nat, ~digest: B.Octets -> B.Octets, key: B.Octets) -> Result<&2, &2, Cr.CrError, CrHmacKey>:
54 Done{CrHmac.key(~bsize, ~digest, key)}
55
56
57def CrHmac.mac(~digest: B.Octets -> B.Octets, kk: CrHmacKey, m: B.Octets) -> B.Octets:
58 match kk:
59 case CrHmacKey{i, o}:
60 digest(B.Octets.append(o, digest(B.Octets.append(i, m))))
61
62
63def CrHmac.verify(~digest: B.Octets -> B.Octets, kk: CrHmacKey, m: B.Octets, t: B.Octets) -> Bool:
64 Mc.CrMac.verify_tag(~CrHmacKey, ~CrHmac.mac(~digest), kk, m, t)
65
66
67def CrHmac.start(~H: Data, ~init: H, ~update: H -> B.Octets -> H, kk: CrHmacKey) -> CrHmacState<H>:
68 match kk:
69 case CrHmacKey{i, o}:
70 CrHmacState{update(init, i), o}
71
72def CrHmac.update(~H: Data, ~update: H -> B.Octets -> H, s: CrHmacState<H>, m: B.Octets) -> CrHmacState<H>:
73 match s:
74 case CrHmacState{h, o}:
75 CrHmacState{update(h, m), o}
76
77def CrHmac.finish(~H: Data, ~init: H, ~update: H -> B.Octets -> H, ~final: H -> B.Octets, s: CrHmacState<H>) -> B.Octets:
78 match s:
79 case CrHmacState{h, o}:
80 final(update(update(init, o), final(h)))