kbkdf.bend
bend-osdev-crypto@0.1.0.0 · 140 lines · 17 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import Base
26import bend-osdev-bytes@0.1.0.0/bytes.bend as B
27import bend-osdev-crypto@0.1.0.0/crypto.bend as Cr
28
29def cr.kb.head(xs: List<&2, U32>) -> U32:
30 match xs:
31 case Con{h, t}:
32 h
33 case Nil{}:
34 0
35
36def cr.kb.tail(xs: List<&2, U32>) -> List<&2, U32>:
37 match xs:
38 case Con{h, t}:
39 t
40 case Nil{}:
41 Nil{}
42
43
44def CrKbkdf.counter(+rlen: Nat, i: U32) -> B.Octets:
45 B.Octets.drop(Nat.sub(4n, rlen), B.Octets.be32(i))
46
47
48
49def cr.kb.ctr(~K: Data, ~compute: K -> B.Octets -> B.Octets, n: Nat, cur: List<&2, U32>, +k: K, +rlen: Nat, +fixed: B.Octets, +i: U32) -> List<&2, U32>:
50 match n:
51 case 0n:
52 Nil{}
53 case 1n+p:
54 match cur:
55 case Con{h, t}:
56 Con{h, cr.kb.ctr(~K, ~compute, p, t, k, rlen, fixed, i)}
57 case Nil{}:
58 +blk = B.Octets.to_list(compute(k, B.Octets.append(CrKbkdf.counter(rlen, U32.add(i, 1)), fixed)))
59 Con{cr.kb.head(blk), cr.kb.ctr(~K, ~compute, p, cr.kb.tail(blk), k, rlen, fixed, U32.add(i, 1))}
60
61
62
63def CrKbkdf.counter_stream(~K: Data, ~compute: K -> B.Octets -> B.Octets, ~rlen: Nat, k: K, fixed: B.Octets, n: Nat) -> B.Octets:
64 B.Octets.of_list(cr.kb.ctr(~K, ~compute, n, Nil{}, k, rlen, fixed, 0))
65
66
67
68def cr.kb.fb(~K: Data, ~compute: K -> B.Octets -> B.Octets, n: Nat, cur: List<&2, U32>, +k: K, +rlen: Nat, +fixed: B.Octets, +prev: B.Octets, +i: U32) -> List<&2, U32>:
69 match n:
70 case 0n:
71 Nil{}
72 case 1n+p:
73 match cur:
74 case Con{h, t}:
75 Con{h, cr.kb.fb(~K, ~compute, p, t, k, rlen, fixed, prev, i)}
76 case Nil{}:
77 +blk = compute(k, B.Octets.append(prev, B.Octets.append(CrKbkdf.counter(rlen, U32.add(i, 1)), fixed)))
78 +bl = B.Octets.to_list(blk)
79 Con{cr.kb.head(bl), cr.kb.fb(~K, ~compute, p, cr.kb.tail(bl), k, rlen, fixed, blk, U32.add(i, 1))}
80
81
82
83def CrKbkdf.feedback_stream(~K: Data, ~compute: K -> B.Octets -> B.Octets, ~rlen: Nat, k: K, iv: B.Octets, fixed: B.Octets, n: Nat) -> B.Octets:
84 B.Octets.of_list(cr.kb.fb(~K, ~compute, n, Nil{}, k, rlen, fixed, iv, 0))
85
86
87def CrKbkdf.length(+llen: Nat, +n: Nat) -> B.Octets:
88 B.Octets.drop(Nat.sub(4n, llen), B.Octets.be32(U32.from_nat(Nat.mul(8n, n))))
89
90
91def CrKbkdf.fixed(~llen: Nat, label: B.Octets, context: B.Octets, +n: Nat) -> B.Octets:
92 B.Octets.concat([label, B.Octets.of_list([0]), context, CrKbkdf.length(llen, n)])
93
94
95
96def cr.kb.fits(+hlen: Nat, +llen: Nat, +n: Nat, +max: Nat) -> Bool:
97 Bool.and(Bool.and(Nat.is_lt(0n, hlen), Nat.is_le(Nat.div(Nat.add(n, Nat.sub(hlen, 1n)), hlen), max)), Nat.is_lt(Nat.mul(8n, n), Nat.pow(2n, Nat.mul(8n, Nat.min(llen, 4n)))))
98
99def cr.kb.key(~K: Data, ~compute: K -> B.Octets -> B.Octets, ~rlen: Nat, kr: Result<&2, &2, Cr.CrError, K>, fixed: B.Octets, n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
100 match kr:
101 case Fail{e}:
102 Fail{e}
103 case Done{k}:
104 Done{CrKbkdf.counter_stream(~K, ~compute, ~rlen, k, fixed, n)}
105
106def cr.kb.checked(~K: Data, ~compute: K -> B.Octets -> B.Octets, ~rlen: Nat, fits: Bool, kr: Result<&2, &2, Cr.CrError, K>, fixed: B.Octets, +n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
107 match fits:
108 case False{}:
109 Fail{Cr.CrBadOutputLength{n}}
110 case True{}:
111 cr.kb.key(~K, ~compute, ~rlen, kr, fixed, n)
112
113
114
115def CrKbkdf.counter_kdf(~K: Data, ~key: B.Octets -> Result<&2, &2, Cr.CrError, K>, ~compute: K -> B.Octets -> B.Octets, ~hlen: Nat, ~rlen: Nat, ~llen: Nat, ki: B.Octets, label: B.Octets, context: B.Octets, +n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
116 +max = Nat.sub(Nat.pow(2n, Nat.mul(8n, rlen)), 1n)
117 cr.kb.checked(~K, ~compute, ~rlen, cr.kb.fits(hlen, llen, n, max), key(ki), CrKbkdf.fixed(~llen, label, context, n), n)
118
119def cr.kb.fkey(~K: Data, ~compute: K -> B.Octets -> B.Octets, ~rlen: Nat, kr: Result<&2, &2, Cr.CrError, K>, iv: B.Octets, fixed: B.Octets, n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
120 match kr:
121 case Fail{e}:
122 Fail{e}
123 case Done{k}:
124 Done{CrKbkdf.feedback_stream(~K, ~compute, ~rlen, k, iv, fixed, n)}
125
126def cr.kb.fchecked(~K: Data, ~compute: K -> B.Octets -> B.Octets, ~rlen: Nat, fits: Bool, kr: Result<&2, &2, Cr.CrError, K>, iv: B.Octets, fixed: B.Octets, +n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
127 match fits:
128 case False{}:
129 Fail{Cr.CrBadOutputLength{n}}
130 case True{}:
131 cr.kb.fkey(~K, ~compute, ~rlen, kr, iv, fixed, n)
132
133
134def CrKbkdf.feedback_kdf(~K: Data, ~key: B.Octets -> Result<&2, &2, Cr.CrError, K>, ~compute: K -> B.Octets -> B.Octets, ~hlen: Nat, ~rlen: Nat, ~llen: Nat, ki: B.Octets, iv: B.Octets, label: B.Octets, context: B.Octets, +n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
135 cr.kb.fchecked(~K, ~compute, ~rlen, cr.kb.fits(hlen, llen, n, 4294967295n), key(ki), iv, CrKbkdf.fixed(~llen, label, context, n), n)
136
137
138
139def CrKbkdf.derive(~K: Data, ~key: B.Octets -> Result<&2, &2, Cr.CrError, K>, ~compute: K -> B.Octets -> B.Octets, ~hlen: Nat, ~rlen: Nat, ~llen: Nat, secret: B.Octets, salt: B.Octets, info: B.Octets, n: Nat) -> Result<&2, &2, Cr.CrError, B.Octets>:
140 CrKbkdf.counter_kdf(~K, ~key, ~compute, ~hlen, ~rlen, ~llen, secret, salt, info, n)