package hacl-star

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file SharedFunctors.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
open Unsigned

open SharedDefs
open AutoConfig2

let check_reqs = List.iter (fun x -> assert (has_feature x))

module Make_Chacha20_Poly1305_generic (C: Buffer)
    (Impl : sig
       val reqs : feature list
       val encrypt : C.buf -> C.buf -> uint32 -> C.buf -> uint32 -> C.buf -> C.buf -> C.buf -> unit
       val decrypt : C.buf -> C.buf -> uint32 -> C.buf -> uint32 -> C.buf -> C.buf -> C.buf -> uint32
     end)
= struct
  type bytes = C.t
  open AEADDefs
  let alg = CHACHA20_POLY1305

  module Noalloc = struct
    let encrypt ~key ~iv ~ad ~pt ~ct ~tag =
      check_reqs Impl.reqs;
      (* code/chacha20poly1305/Hacl.Impl.Chacha20Poly1305.aead_encrypt_st *)
      check_sizes ~alg ~iv_len:(C.size iv) ~tag_len:(C.size tag)
        ~ad_len:(C.size ad)~pt_len:(C.size pt) ~ct_len:(C.size ct);
      assert (C.disjoint key ct);
      assert (C.disjoint iv ct);
      assert (C.disjoint key tag);
      assert (C.disjoint iv tag);
      assert (C.disjoint ct tag);
      assert (C.disjoint ad ct);
      Impl.encrypt (C.ctypes_buf key) (C.ctypes_buf iv) (C.size_uint32 ad) (C.ctypes_buf ad)
        (C.size_uint32 pt) (C.ctypes_buf pt) (C.ctypes_buf ct) (C.ctypes_buf tag)
    let decrypt ~key ~iv ~ad ~ct ~tag ~pt =
      check_reqs Impl.reqs;
      (* code/chacha20poly1305/Hacl.Impl.Chacha20Poly1305.aead_decrypt_st *)
      check_sizes ~alg ~iv_len:(C.size iv) ~tag_len:(C.size tag)
        ~ad_len:(C.size ad)~pt_len:(C.size pt) ~ct_len:(C.size ct);
      let result = Impl.decrypt (C.ctypes_buf key) (C.ctypes_buf iv) (C.size_uint32 ad) (C.ctypes_buf ad)
          (C.size_uint32 pt) (C.ctypes_buf pt) (C.ctypes_buf ct) (C.ctypes_buf tag)
      in
      UInt32.to_int result = 0
  end
  let encrypt ~key ~iv ~ad ~pt =
    let ct = C.make (C.size pt) in
    let tag = C.make (tag_length alg) in
    Noalloc.encrypt ~key ~iv ~ad ~pt ~ct ~tag;
    (ct, tag)
  let decrypt ~key ~iv ~ad ~ct ~tag =
    let pt = C.make (C.size ct) in
    if Noalloc.decrypt ~key ~iv ~ad ~ct ~tag ~pt then
      Some pt
    else
      None
end

module Make_Curve25519_generic (C: Buffer)
    (Impl : sig
       val reqs : feature list
       val secret_to_public : C.buf -> C.buf -> unit
       val scalarmult : C.buf -> C.buf -> C.buf -> unit
       val ecdh : C.buf -> C.buf -> C.buf -> bool
  end)
= struct
  type bytes = C.t
  module Noalloc = struct
    let secret_to_public ~sk ~pk =
      check_reqs Impl.reqs;
      (* Hacl.Impl.Curve25519.Generic.secret_to_public_st *)
      assert (C.disjoint pk sk);
      assert (C.size pk = 32);
      assert (C.size sk = 32);
      Impl.secret_to_public (C.ctypes_buf pk) (C.ctypes_buf sk)
    let scalarmult ~scalar ~point ~result =
      check_reqs Impl.reqs;
      (* Hacl.Impl.Curve25519.Generic.scalarmult_st *)
      assert (C.disjoint result scalar);
      assert (C.disjoint result point);
      assert (C.size result = 32);
      assert (C.size scalar = 32);
      assert (C.size point = 32);
      Impl.scalarmult (C.ctypes_buf result) (C.ctypes_buf scalar) (C.ctypes_buf point)
    let ecdh ~sk ~pk ~shared =
      check_reqs Impl.reqs;
      (* Hacl.Impl.Curve25519.Generic.ecdh_st *)
      assert (C.disjoint shared sk);
      assert (C.disjoint shared pk);
      assert (C.size shared = 32);
      assert (C.size sk = 32);
      assert (C.size pk = 32);
      Impl.ecdh (C.ctypes_buf shared) (C.ctypes_buf sk) (C.ctypes_buf pk)
  end
  let secret_to_public ~sk =
    let pk = C.make 32 in
    Noalloc.secret_to_public ~sk ~pk;
    pk
  let scalarmult ~scalar ~point =
    let result = C.make 32 in
    Noalloc.scalarmult ~scalar ~point ~result;
    result
  let ecdh ~sk ~pk =
    let shared = C.make 32 in
    if Noalloc.ecdh ~sk ~pk ~shared then
      Some shared
    else
      None
end

module Make_EdDSA_generic (C: Buffer)
    (Impl : sig
  val secret_to_public : C.buf -> C.buf -> unit
  val sign : C.buf -> C.buf -> uint32 -> C.buf -> unit
  val verify : C.buf -> uint32 -> C.buf -> C.buf -> bool
  val expand_keys : C.buf -> C.buf -> unit
  val sign_expanded : C.buf -> C.buf -> uint32 -> C.buf -> unit
  end)
= struct
  type bytes = C.t
  let verify ~pk ~msg ~signature =
    (* Hacl.Ed25519.verify *)
    assert (C.size pk = 32);
    assert (C.size signature = 64);
    assert Z.(of_int (C.size msg) <= max_uint32);
    Impl.verify (C.ctypes_buf pk) (C.size_uint32 msg) (C.ctypes_buf msg) (C.ctypes_buf signature)
  module Noalloc = struct
    let secret_to_public ~sk ~pk =
      (* Hacl.Ed25519.secret_to_public *)
      assert (C.size pk = 32);
      assert (C.size sk = 32);
      assert (C.disjoint pk sk);
      Impl.secret_to_public (C.ctypes_buf pk) (C.ctypes_buf sk)
    let sign ~sk ~msg ~signature =
      (* Hacl.Ed25519.sign *)
      assert (C.size sk = 32);
      assert (C.size signature = 64);
      assert Z.(of_int (C.size msg) <= max_uint32);
      Impl.sign (C.ctypes_buf signature) (C.ctypes_buf sk) (C.size_uint32 msg) (C.ctypes_buf msg)
    let expand_keys ~sk ~ks =
      (* Hacl.Ed25519.expand_keys *)
      assert (C.size ks = 96);
      assert (C.size sk = 32);
      assert (C.disjoint ks sk); (* VD: redundant for Bytes, since size is different *)
      Impl.expand_keys (C.ctypes_buf ks) (C.ctypes_buf sk)
    let sign_expanded ~ks ~msg ~signature =
      (* Hacl.Ed25519.sign_expanded *)
      assert (C.size ks = 96);
      assert (C.size signature = 64);
      assert Z.(of_int (C.size msg) <= max_uint32);
      Impl.sign_expanded (C.ctypes_buf signature) (C.ctypes_buf ks) (C.size_uint32 msg) (C.ctypes_buf msg)
  end
  let secret_to_public ~sk =
    let pk = C.make 32 in
    Noalloc.secret_to_public ~sk ~pk;
    pk
  let sign ~sk ~msg =
    let signature = C.make 64 in
    Noalloc.sign ~sk ~msg ~signature;
    signature
  let expand_keys ~sk =
    let ks = C.make 96 in
    Noalloc.expand_keys ~sk ~ks;
    ks
  let sign_expanded ~ks ~msg =
    let signature = C.make 64 in
    Noalloc.sign_expanded ~ks ~msg ~signature;
    signature
end

(* HashDefs only defines algorithms that are included in the EverCrypt agile hashing interface.
   In addition to these, HACL* also includes SHA-3. We  extend the `hash_alg` type so we can
   use the same functor for all hash functions. *)
type all_hash_alg =
  | Agile of HashDefs.alg
  | SHA3_224
  | SHA3_256
  | SHA3_384
  | SHA3_512

module Make_HashFunction_generic (C: Buffer)
    (Impl : sig
       val hash_alg : all_hash_alg
       val hash : C.buf -> uint32 -> C.buf -> unit
     end)
= struct
  type bytes = C.t
  let digest_len = function
    | SHA3_224 -> 28
    | SHA3_256 -> 32
    | SHA3_384 -> 48
    | SHA3_512 -> 64
    | Agile alg -> HashDefs.digest_len alg
  module Noalloc = struct
    let hash ~msg ~digest =
      check_max_buffer_len (C.size msg);
      assert (C.size digest = digest_len Impl.hash_alg);
      assert (C.disjoint msg digest);
      Impl.hash (C.ctypes_buf msg) (C.size_uint32 msg) (C.ctypes_buf digest)
  end
  let hash msg =
    let digest = C.make (digest_len Impl.hash_alg) in
    Noalloc.hash ~msg ~digest;
    digest
end

module Make_Poly1305_generic (C: Buffer)
    (Impl : sig
       val reqs : feature list
       val mac : C.buf -> uint32 -> C.buf -> C.buf -> unit
     end)
= struct
  type bytes = C.t
  module Noalloc = struct
    let mac ~key ~msg ~tag =
      check_reqs Impl.reqs;
      (* Hacl.Impl.Poly1305.poly1305_mac_st *)
      assert (C.size tag = 16);
      assert (C.size key = 32);
      assert (C.disjoint tag msg);
      assert (C.disjoint key msg);
      Impl.mac (C.ctypes_buf tag) (C.size_uint32 msg) (C.ctypes_buf msg) (C.ctypes_buf key)
  end
  let mac ~key ~msg =
    let tag = C.make 16 in
    Noalloc.mac ~key ~msg ~tag;
    tag
end

module Make_HMAC_generic (C: Buffer)
    (Impl : sig
       val hash_alg : HashDefs.alg
       val mac : C.buf -> C.buf -> uint32 -> C.buf -> uint32 -> unit
  end)
= struct
  type bytes = C.t
  module Noalloc = struct
    let mac ~key ~msg ~tag =
      (* Hacl.HMAC.compute_st *)
      assert (HashDefs.digest_len Impl.hash_alg = C.size tag);
      assert (C.disjoint tag key);
      check_max_buffer_len (C.size key);
      check_max_buffer_len (C.size msg);
      Impl.mac (C.ctypes_buf tag) (C.ctypes_buf key) (C.size_uint32 key) (C.ctypes_buf msg) (C.size_uint32 msg)
  end
  let mac ~key ~msg =
    let tag = C.make (HashDefs.digest_len Impl.hash_alg) in
    Noalloc.mac ~key ~msg ~tag;
    tag
end

module Make_HKDF_generic (C: Buffer)
    (Impl: sig
       val hash_alg : HashDefs.alg
       val extract : C.buf -> C.buf -> uint32 -> C.buf -> uint32 -> unit
       val expand : C.buf -> C.buf -> uint32 -> C.buf -> uint32 -> uint32 -> unit
     end)
= struct
  type bytes = C.t
  module Noalloc = struct
    let extract ~salt ~ikm ~prk =
      (* Hacl.HKDF.extract_st *)
      assert (C.size prk = HashDefs.digest_len Impl.hash_alg);
      assert (C.disjoint salt prk);
      assert (C.disjoint ikm prk);
      check_max_buffer_len (C.size salt);
      check_max_buffer_len (C.size ikm);
      Impl.extract (C.ctypes_buf prk) (C.ctypes_buf salt) (C.size_uint32 salt) (C.ctypes_buf ikm) (C.size_uint32 ikm)
    let expand ~prk ~info ~okm =
      (* Hacl.HKDF.expand_st *)
      assert (C.size okm <= 255 * HashDefs.digest_len Impl.hash_alg);
      assert (C.disjoint okm prk);
      assert (HashDefs.digest_len Impl.hash_alg <= C.size prk);
      check_max_buffer_len (C.size info);
      check_max_buffer_len (C.size prk);
      Impl.expand (C.ctypes_buf okm) (C.ctypes_buf prk) (C.size_uint32 prk) (C.ctypes_buf info) (C.size_uint32 info) (C.size_uint32 okm)
  end
  let extract ~salt ~ikm =
    let prk = C.make (HashDefs.digest_len Impl.hash_alg) in
    Noalloc.extract ~salt ~ikm ~prk;
    prk
  let expand ~prk ~info ~size =
    let okm = C.make size in
    Noalloc.expand ~prk ~info ~okm;
    okm
end

module Make_ECDSA_generic (C: Buffer)
    (Impl : sig
       val min_msg_size : int
       val sign : C.buf -> uint32 -> C.buf -> C.buf -> C.buf -> bool
       val verify : uint32 -> C.buf -> C.buf -> C.buf -> C.buf -> bool
     end)
= struct
  type bytes = C.t
  let get_result r =
    if r = UInt64.zero then
      true
    else
    if r = UInt64.max_int then
      false
    else
      failwith "Unknown return value"
  let prime_p256_order = Z.of_string "115792089210356248762697446949407573529996955224135760342422259061068512044369"
  module Noalloc = struct
    let sign ~sk ~msg ~k ~signature =
      (* Hacl.Interface.P256.ECDSA.ecdsa_sign_p256_without_hash/sha2/sha384 *)
      assert (C.size signature = 64);
      assert (C.size sk = 32);
      assert (C.size k = 32);
      assert (C.size msg >= Impl.min_msg_size);
      assert (C.disjoint signature msg);
      assert (C.z_compare sk prime_p256_order < 0);
      assert (C.z_compare k prime_p256_order < 0);
      Impl.sign (C.ctypes_buf signature) (C.size_uint32 msg) (C.ctypes_buf msg) (C.ctypes_buf sk) (C.ctypes_buf k)
  end
  let sign ~sk ~msg ~k =
    let signature = C.make 64 in
    if Noalloc.sign ~sk ~msg ~k ~signature then
      Some signature
    else
      None
  let verify ~pk ~msg ~signature =
    (* Hacl.Interface.P256.ECDSA.ecdsa_verif_without_hash/sha2/sha384 *)
    assert (C.size signature = 64);
    assert (C.size pk = 64);
    assert (C.size msg >= Impl.min_msg_size);
    let r, s = C.sub signature 0 32, C.sub signature 32 32 in
    Impl.verify (C.size_uint32 msg) (C.ctypes_buf msg) (C.ctypes_buf pk) (C.ctypes_buf r) (C.ctypes_buf s)
end


module Make_Blake2b_generic (C: Buffer)
    (Impl : sig
       val reqs : feature list
       val blake2b : uint32 -> C.buf -> uint32 -> C.buf -> uint32 -> C.buf -> unit
     end)
= struct
  type bytes = C.t
  module Noalloc = struct
    let hash ~key ~msg ~digest =
      check_reqs Impl.reqs;
      (* specs/Spec.Blake2.blake2b *)
      check_max_buffer_len (C.size msg);
      assert (C.size digest > 0 && C.size digest <= 64);
      assert (C.size key <= 64);
      assert (C.disjoint key msg);
      assert (C.disjoint key digest);
      assert (C.disjoint msg digest);
      Impl.blake2b (C.size_uint32 digest) (C.ctypes_buf digest) (C.size_uint32 msg) (C.ctypes_buf msg) (C.size_uint32 key) (C.ctypes_buf key)
  end
  let hash ?(key = C.empty) msg size =
    assert (size > 0 && size <= 64);
    let digest = C.make size in
    Noalloc.hash ~key ~msg ~digest;
    digest
end

module Make_Blake2s_generic (C: Buffer)
    (Impl : sig
       val reqs : feature list
       val blake2s : uint32 -> C.buf -> uint32 -> C.buf -> uint32 -> C.buf -> unit
     end)
= struct
  type bytes = C.t
  module Noalloc = struct
    let hash ~key ~msg ~digest =
      check_reqs Impl.reqs;
      (* specs/Spec.Blake2.blake2s *)
      check_max_buffer_len (C.size msg);
      assert (C.size digest > 0 && C.size digest <= 32);
      assert (C.size key <= 32);
      assert (C.disjoint key msg);
      assert (C.disjoint key digest);
      assert (C.disjoint msg digest);
      Impl.blake2s (C.size_uint32 digest) (C.ctypes_buf digest) (C.size_uint32 msg) (C.ctypes_buf msg) (C.size_uint32 key) (C.ctypes_buf key)
  end
  let hash ?(key = C.empty) msg size =
    assert (size > 0 && size <= 32);
    let digest = C.make size in
    Noalloc.hash ~key ~msg ~digest;
    digest
end

module Make_Chacha20_Poly1305 = Make_Chacha20_Poly1305_generic (CBytes)
module Make_Curve25519 = Make_Curve25519_generic (CBytes)
module Make_EdDSA = Make_EdDSA_generic (CBytes)
module Make_HashFunction = Make_HashFunction_generic (CBytes)
module Make_Poly1305 = Make_Poly1305_generic (CBytes)
module Make_HMAC = Make_HMAC_generic (CBytes)
module Make_HKDF = Make_HKDF_generic (CBytes)
module Make_ECDSA = Make_ECDSA_generic (CBytes)
module Make_Blake2b = Make_Blake2b_generic (CBytes)
module Make_Blake2s = Make_Blake2s_generic (CBytes)
OCaml

Innovation. Community. Security.