···1-# mirage-crypto - Cryptographic primitives for MirageOS
23-%%VERSION%%
00000045mirage-crypto is a small cryptographic library that puts emphasis on the
6applicative style and ease of use. It includes basic ciphers (AES, 3DES, RC4,
···1314Mirage-crypto is a fork of the
15[ocaml-nocrypto](https://github.com/mirleft/ocaml-nocrypto) written by David
16-Kaloper. It was forked with the permission of the original author in order to
17facilitate changes (e.g. build system) required by Mirage that the upstream
18didn't have time to keep up with.
19-20-Mirage-crypto-rng embeds the former mirage-entropy opam package, which
21-implements various entropy sources:
22-- non-deterministic execution time (used at initial seeding, see the [whirlwind RNG paper](https://www.ieee-security.org/TC/SP2014/papers/Not-So-RandomNumbersinVirtualizedLinuxandtheWhirlwindRNG.pdf))
23-- a hook into the Lwt event loop that collects a timestamp of each event
24-- rdseed and rdrand (x86/x86-64 only)
25-26-[API documentation online](https://mirage.github.io/mirage-crypto/doc)
2728## Build
29···40seed it.
4142```OCaml
43-let () = Mirage_crypto_rng_unix.use_default ()
44```
···1+# crypto - Cryptographic primitives for OCaml
23+> **Warning**: This is an experimental fork of [mirage-crypto](https://github.com/mirage/mirage-crypto).
4+> Do not use in production. Use [mirage-crypto](https://github.com/mirage/mirage-crypto) instead.
5+6+This fork renames the packages and removes Lwt/Miou dependencies, keeping only
7+Eio-compatible code. It is intended for experimentation only.
8+9+## Original mirage-crypto
1011mirage-crypto is a small cryptographic library that puts emphasis on the
12applicative style and ease of use. It includes basic ciphers (AES, 3DES, RC4,
···1920Mirage-crypto is a fork of the
21[ocaml-nocrypto](https://github.com/mirleft/ocaml-nocrypto) written by David
22+Kaloper. It was forked with the permission of the original author in order to
23facilitate changes (e.g. build system) required by Mirage that the upstream
24didn't have time to keep up with.
000000002526## Build
27···38seed it.
3940```OCaml
41+let () = Crypto_rng_unix.use_default ()
42```
+1-9
bench/dune
···1(executables
2 (names speed)
3 (modules speed)
4- (libraries mirage-crypto mirage-crypto-rng mirage-crypto-rng.unix
5- mirage-crypto-pk mirage-crypto-ec))
6-7-; marking as "(optional)" leads to OCaml-CI failures
8-; marking with "(package mirage-crypto-rng-miou-unix)" only has an effect with a "public_name"
9-;(executables
10-; (names miou)
11-; (modules miou)
12-; (libraries mirage-crypto-rng-miou-unix))
···1-open Mirage_crypto
2-3-module Time = struct
4-5- let time ~n f a =
6- let t1 = Sys.time () in
7- for _ = 1 to n do ignore (f a) done ;
8- let t2 = Sys.time () in
9- (t2 -. t1)
10-11- let warmup () =
12- let x = ref 0 in
13- let rec go start =
14- if Sys.time () -. start < 1. then begin
15- for i = 0 to 10000 do x := !x + i done ;
16- go start
17- end in
18- go (Sys.time ())
19-20-end
21-22-let burn_period = 2.0
23-24-let sizes = [16; 64; 256; 1024; 8192]
25-(* let sizes = [16] *)
26-27-let burn f n =
28- let buf = Mirage_crypto_rng.generate n in
29- let (t1, i1) =
30- let rec loop it =
31- let t = Time.time ~n:it f buf in
32- if t > 0.2 then (t, it) else loop (it * 10) in
33- loop 10 in
34- let iters = int_of_float (float i1 *. burn_period /. t1) in
35- let time = Time.time ~n:iters f buf in
36- (iters, time, float (n * iters) /. time)
37-38-let mb = 1024. *. 1024.
39-40-let throughput title f =
41- Printf.printf "\n* [%s]\n%!" title ;
42- sizes |> List.iter @@ fun size ->
43- Gc.full_major () ;
44- let (iters, time, bw) = burn f size in
45- Printf.printf " % 5d: %04f MB/s (%d iters in %.03f s)\n%!"
46- size (bw /. mb) iters time
47-48-let bm name f = (name, fun () -> f name)
49-50-let benchmarks = [
51- bm "pfortuna" (fun name ->
52- let open Mirage_crypto_rng_miou_unix.Pfortuna in
53- Miou_unix.run ~domains:2 @@ fun () ->
54- let rng = Mirage_crypto_rng_miou_unix.(initialize (module Pfortuna)) in
55- let g = create () in
56- reseed ~g "abcd" ;
57- throughput name (fun buf ->
58- let buf = Bytes.unsafe_of_string buf in
59- generate_into ~g buf ~off:0 (Bytes.length buf));
60- Mirage_crypto_rng_miou_unix.kill rng) ;
61-]
62-63-let help () =
64- Printf.printf "available benchmarks:\n ";
65- List.iter (fun (n, _) -> Printf.printf "%s " n) benchmarks ;
66- Printf.printf "\n%!"
67-68-let runv fs =
69- Format.printf "accel: %a\n%!"
70- (fun ppf -> List.iter @@ fun x ->
71- Format.fprintf ppf "%s " @@
72- match x with `XOR -> "XOR" | `AES -> "AES" | `GHASH -> "GHASH")
73- accelerated;
74- Time.warmup () ;
75- List.iter (fun f -> f ()) fs
76-77-78-let () =
79- let seed = "abcd" in
80- let g = Mirage_crypto_rng.(create ~seed (module Fortuna)) in
81- Mirage_crypto_rng.set_default_generator g;
82- match Array.to_list Sys.argv with
83- | _::(_::_ as args) -> begin
84- try
85- let fs =
86- args |> List.map @@ fun n ->
87- snd (benchmarks |> List.find @@ fun (n1, _) -> n = n1) in
88- runv fs
89- with Not_found -> help ()
90- end
91- | _ -> help ()
···39 val secret_of_octets : ?compress:bool -> string ->
40 (secret * string, error) result
41 val secret_to_octets : secret -> string
42- val gen_key : ?compress:bool -> ?g:Mirage_crypto_rng.g -> unit ->
43 secret * string
44 val key_exchange : secret -> string -> (string, error) result
45end
···54 val pub_of_octets : string -> (pub, error) result
55 val pub_to_octets : ?compress:bool -> pub -> string
56 val pub_of_priv : priv -> pub
57- val generate : ?g:Mirage_crypto_rng.g -> unit -> priv * pub
58 val sign : key:priv -> ?k:string -> string -> string * string
59 val verify : key:pub -> string * string -> string -> bool
60 module K_gen (H : Digestif.S) : sig
···523 S.to_octets s
524525 let rec generate_private_key ?g () =
526- let candidate = Mirage_crypto_rng.generate ?g Param.byte_length in
527 match S.of_octets candidate with
528 | Ok secret -> secret
529 | Error _ -> generate_private_key ?g ()
···640641 (* RFC 6979: compute a deterministic k *)
642 module K_gen (H : Digestif.S) = struct
643- let drbg : 'a Mirage_crypto_rng.generator =
644- let module M = Mirage_crypto_rng.Hmac_drbg (H) in (module M)
645646 let g ~key msg =
647- let g = Mirage_crypto_rng.create ~strict:true drbg in
648- Mirage_crypto_rng.reseed ~g (S.to_octets key ^ msg);
649 g
650651 (* Defined in RFC 6979 sec 2.3.2 with
···672 let gen g =
673 let rec go () =
674 let b = Bytes.create Param.byte_length in
675- Mirage_crypto_rng.generate_into ~g b Param.byte_length;
676 (* truncate to the desired number of bits *)
677 let r = bits2int b in
678 if S.is_in_range r then r else go ()
···694 (* FIPS 186-4 B 4.2 *)
695 let d =
696 let rec one () =
697- match S.of_octets (Mirage_crypto_rng.generate ?g Param.byte_length) with
698 | Ok x -> x
699 | Error _ -> one ()
700 in
···978 let public priv = scalar_mult priv basepoint
979980 let gen_key ?compress:_ ?g () =
981- let secret = Mirage_crypto_rng.generate ?g key_len in
982 secret, public secret
983984 let secret_of_octets ?compress:_ s =
···1072 let pub_to_octets pub = pub
10731074 let generate ?g () =
1075- let secret = Mirage_crypto_rng.generate ?g key_len in
1076 secret, pub_of_priv secret
10771078 let sign ~key msg =
···39 val secret_of_octets : ?compress:bool -> string ->
40 (secret * string, error) result
41 val secret_to_octets : secret -> string
42+ val gen_key : ?compress:bool -> ?g:Crypto_rng.g -> unit ->
43 secret * string
44 val key_exchange : secret -> string -> (string, error) result
45end
···54 val pub_of_octets : string -> (pub, error) result
55 val pub_to_octets : ?compress:bool -> pub -> string
56 val pub_of_priv : priv -> pub
57+ val generate : ?g:Crypto_rng.g -> unit -> priv * pub
58 val sign : key:priv -> ?k:string -> string -> string * string
59 val verify : key:pub -> string * string -> string -> bool
60 module K_gen (H : Digestif.S) : sig
···523 S.to_octets s
524525 let rec generate_private_key ?g () =
526+ let candidate = Crypto_rng.generate ?g Param.byte_length in
527 match S.of_octets candidate with
528 | Ok secret -> secret
529 | Error _ -> generate_private_key ?g ()
···640641 (* RFC 6979: compute a deterministic k *)
642 module K_gen (H : Digestif.S) = struct
643+ let drbg : 'a Crypto_rng.generator =
644+ let module M = Crypto_rng.Hmac_drbg (H) in (module M)
645646 let g ~key msg =
647+ let g = Crypto_rng.create ~strict:true drbg in
648+ Crypto_rng.reseed ~g (S.to_octets key ^ msg);
649 g
650651 (* Defined in RFC 6979 sec 2.3.2 with
···672 let gen g =
673 let rec go () =
674 let b = Bytes.create Param.byte_length in
675+ Crypto_rng.generate_into ~g b Param.byte_length;
676 (* truncate to the desired number of bits *)
677 let r = bits2int b in
678 if S.is_in_range r then r else go ()
···694 (* FIPS 186-4 B 4.2 *)
695 let d =
696 let rec one () =
697+ match S.of_octets (Crypto_rng.generate ?g Param.byte_length) with
698 | Ok x -> x
699 | Error _ -> one ()
700 in
···978 let public priv = scalar_mult priv basepoint
979980 let gen_key ?compress:_ ?g () =
981+ let secret = Crypto_rng.generate ?g key_len in
982 secret, public secret
983984 let secret_of_octets ?compress:_ s =
···1072 let pub_to_octets pub = pub
10731074 let generate ?g () =
1075+ let secret = Crypto_rng.generate ?g key_len in
1076 secret, pub_of_priv secret
10771078 let sign ~key msg =
+3-3
ec/mirage_crypto_ec.mli
ec/crypto_ec.mli
···42 (** [secret_to_octets secret] encodes the provided secret into a freshly
43 allocated buffer. *)
4445- val gen_key : ?compress:bool -> ?g:Mirage_crypto_rng.g -> unit ->
46 secret * string
47 (** [gen_key ~compress ~g ()] generates a private and a public key for
48 Ephemeral Diffie-Hellman. If [compress] is provided and [true] (defaults
···107108 (** {2 Key generation} *)
109110- val generate : ?g:Mirage_crypto_rng.g -> unit -> priv * pub
111 (** [generate ~g ()] generates a key pair. *)
112113 (** {2 Cryptographic operations} *)
···245246 (** {2 Key generation} *)
247248- val generate : ?g:Mirage_crypto_rng.g -> unit -> priv * pub
249 (** [generate ~g ()] generates a key pair. *)
250251 (** {2 Cryptographic operations} *)
···42 (** [secret_to_octets secret] encodes the provided secret into a freshly
43 allocated buffer. *)
4445+ val gen_key : ?compress:bool -> ?g:Crypto_rng.g -> unit ->
46 secret * string
47 (** [gen_key ~compress ~g ()] generates a private and a public key for
48 Ephemeral Diffie-Hellman. If [compress] is provided and [true] (defaults
···107108 (** {2 Key generation} *)
109110+ val generate : ?g:Crypto_rng.g -> unit -> priv * pub
111 (** [generate ~g ()] generates a key pair. *)
112113 (** {2 Cryptographic operations} *)
···245246 (** {2 Key generation} *)
247248+ val generate : ?g:Crypto_rng.g -> unit -> priv * pub
249 (** [generate ~g ()] generates a key pair. *)
250251 (** {2 Cryptographic operations} *)
+1-1
ec/native/curve25519_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+1-1
ec/native/np256_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+1-1
ec/native/np384_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+1-1
ec/native/np521_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+1-1
ec/native/p256_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+1-1
ec/native/p384_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+1-1
ec/native/p521_stubs.c
···1-#include "mirage_crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
···1+#include "crypto.h"
23/* Microsoft compiler does not support 128-bit integers. Drop down to
4 * 32-bit for MSVC.
+9-7
mirage-crypto-ec.opam
crypto-ec.opam
···1opam-version: "2.0"
2-synopsis: "Elliptic Curve Cryptography with primitives taken from Fiat"
3description: """
0004An implementation of key exchange (ECDH) and digital signature (ECDSA/EdDSA)
5algorithms using code from Fiat (<https://github.com/mit-plv/fiat-crypto>).
67The curves P256 (SECP256R1), P384 (SECP384R1),
8P521 (SECP521R1), and 25519 (X25519, Ed25519) are implemented by this package.
9"""
10-maintainer: "Hannes Mehnert <hannes@mehnert.org>"
11authors: [
12 "Hannes Mehnert <hannes@mehnert.org>"
13 "Nathan Rebours <nathan.p.rebours@gmail.com>"
···22 "Zoe Paraskevopoulou <zoe.paraskevopoulou@gmail.com>"
23]
24license: "MIT"
25-homepage: "https://github.com/mirage/mirage-crypto"
26-doc: "https://mirage.github.io/mirage-crypto/doc"
27-bug-reports: "https://github.com/mirage/mirage-crypto/issues"
28depends: [
29 "dune" {>= "2.7"}
30 "ocaml" {>= "4.13.0"}
31 "dune-configurator"
32 "eqaf" {>= "0.7"}
33- "mirage-crypto-rng" {=version}
34 "digestif" {>= "1.2.0"}
35 "alcotest" {with-test & >= "0.8.1"}
36 "ppx_deriving_yojson" {with-test}
···48 ["dune" "build" "-p" name "-j" jobs]
49 ["dune" "runtest" "-p" name "-j" jobs] {with-test}
50]
51-dev-repo: "git+https://github.com/mirage/mirage-crypto.git"
52tags: ["org:mirage"]
53x-maintenance-intent: [ "(latest)" ]
···1opam-version: "2.0"
2+synopsis: "Elliptic Curve Cryptography (fork of mirage-crypto-ec)"
3description: """
4+WARNING: This is an experimental fork of mirage-crypto-ec. Do not use in production.
5+Use mirage-crypto-ec instead: https://github.com/mirage/mirage-crypto
6+7An implementation of key exchange (ECDH) and digital signature (ECDSA/EdDSA)
8algorithms using code from Fiat (<https://github.com/mit-plv/fiat-crypto>).
910The curves P256 (SECP256R1), P384 (SECP384R1),
11P521 (SECP521R1), and 25519 (X25519, Ed25519) are implemented by this package.
12"""
13+maintainer: "Thomas Gazagnaire <thomas@gazagnaire.org>"
14authors: [
15 "Hannes Mehnert <hannes@mehnert.org>"
16 "Nathan Rebours <nathan.p.rebours@gmail.com>"
···25 "Zoe Paraskevopoulou <zoe.paraskevopoulou@gmail.com>"
26]
27license: "MIT"
28+homepage: "https://git.recoil.org/gazagnaire.org/ocaml-crypto"
29+bug-reports: "https://git.recoil.org/gazagnaire.org/ocaml-crypto/issues"
030depends: [
31 "dune" {>= "2.7"}
32 "ocaml" {>= "4.13.0"}
33 "dune-configurator"
34 "eqaf" {>= "0.7"}
35+ "crypto-rng" {=version}
36 "digestif" {>= "1.2.0"}
37 "alcotest" {with-test & >= "0.8.1"}
38 "ppx_deriving_yojson" {with-test}
···50 ["dune" "build" "-p" name "-j" jobs]
51 ["dune" "runtest" "-p" name "-j" jobs] {with-test}
52]
53+dev-repo: "git+ssh://git@git.recoil.org/gazagnaire.org/ocaml-crypto.git"
54tags: ["org:mirage"]
55x-maintenance-intent: [ "(latest)" ]
···1-open Mirage_crypto.Uncommon
23open Common
4···42 if 3 <= l && 2 <= n then (l, n) else
43 invalid_arg "Dsa.generate: bits: `Exactly (%d, %d)" l n
4445-type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
4647let expand_mask = function
48 | `No -> `No
···8485module K_gen (H : Digestif.S) = struct
8687- let drbg : 'a Mirage_crypto_rng.generator =
88- let module M = Mirage_crypto_rng.Hmac_drbg (H) in (module M)
8990 let z_gen ~key:{ q; x; _ } z =
91 let repr = Z_extra.to_octets_be ~size:(Z.numbits q // 8) in
92- let g = Mirage_crypto_rng.create ~strict:true drbg in
93- Mirage_crypto_rng.reseed ~g (repr x ^ repr Z.(z mod q));
94 Z_extra.gen_r ~g Z.one q
9596 let generate ~key buf =
···1+open Crypto.Uncommon
23open Common
4···42 if 3 <= l && 2 <= n then (l, n) else
43 invalid_arg "Dsa.generate: bits: `Exactly (%d, %d)" l n
4445+type mask = [ `No | `Yes | `Yes_with of Crypto_rng.g ]
4647let expand_mask = function
48 | `No -> `No
···8485module K_gen (H : Digestif.S) = struct
8687+ let drbg : 'a Crypto_rng.generator =
88+ let module M = Crypto_rng.Hmac_drbg (H) in (module M)
8990 let z_gen ~key:{ q; x; _ } z =
91 let repr = Z_extra.to_octets_be ~size:(Z.numbits q // 8) in
92+ let g = Crypto_rng.create ~strict:true drbg in
93+ Crypto_rng.reseed ~g (repr x ^ repr Z.(z mod q));
94 Z_extra.gen_r ~g Z.one q
9596 let generate ~key buf =
···73 (** [priv_of_primes ~e ~p ~q] is the {{!type-priv}private key} derived from the
74 minimal description [(e, p, q)]. *)
7576- val priv_of_exp : ?g:Mirage_crypto_rng.g -> ?attempts:int -> e:Z.t -> d:Z.t ->
77 n:Z.t -> unit -> (priv, [> `Msg of string ]) result
78 (** [priv_of_exp ?g ?attempts ~e ~d n] is the unique {{!type-priv}private key}
79 characterized by the public ([e]) and private ([d]) exponents, and modulus
···95 type 'a or_digest = [ `Message of 'a | `Digest of string ]
96 (** Either an ['a] or its digest, according to some hash algorithm. *)
9798- type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
99 (** Masking (cryptographic blinding) mode for the RSA transform with the
100 private key. Masking does not change the result, but it does change the
101 timing profile of the operation.
···132133 (** {1 Key generation} *)
134135- val generate : ?g:Mirage_crypto_rng.g -> ?e:Z.t -> bits:int -> unit -> priv
136 (** [generate ~g ~e ~bits ()] is a new {{!type-priv}private key}. The new key is
137 guaranteed to be well formed, see {!val-priv}.
138···155 key size is [priv_bits key / 8], rounded up. *)
156 module PKCS1 : sig
157158- val encrypt : ?g:Mirage_crypto_rng.g -> key:pub -> string -> string
159 (** [encrypt g key message] is a PKCS1-padded (type 2) and encrypted
160 [message].
161···227 [hlen] is the hash length. *)
228 module OAEP (H : Digestif.S) : sig
229230- val encrypt : ?g:Mirage_crypto_rng.g -> ?label:string -> key:pub ->
231 string -> string
232 (** [encrypt ~g ~label ~key message] is {b OAEP}-padded and encrypted
233 [message], using the optional [label].
···253 hash length and [slen] is the seed length. *)
254 module PSS (H: Digestif.S) : sig
255256- val sign : ?g:Mirage_crypto_rng.g -> ?crt_hardening:bool ->
257 ?mask:mask -> ?slen:int -> key:priv -> string or_digest -> string
258 (** [sign ~g ~crt_hardening ~mask ~slen ~key message] the [PSS]-padded
259 digest of [message], signed with the [key]. [crt_hardening] defaults
···322 L-values ([p] size) and imply the corresponding N ([q] size); The last
323 variants specifies L and N directly. *)
324325- type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
326 (** Masking (cryptographic blinding) option. *)
327328 val pub_of_priv : priv -> pub
329 (** Extract the public component from a private key. *)
330331- val generate : ?g:Mirage_crypto_rng.g -> keysize -> priv
332 (** [generate g size] is a fresh {{!type-priv}private} key. The domain parameters
333 are derived using a modified FIPS.186-4 probabilistic process, but the
334 derivation can not be validated. Note that no time masking is done for the
···416417 @raise Invalid_key if [s] is degenerate. *)
418419- val gen_key : ?g:Mirage_crypto_rng.g -> ?bits:int -> group -> secret * string
420 (** Generate a random {!secret} and the corresponding public key.
421 [bits] is the exact bit-size of {!secret} and defaults to a value
422 dependent on the {!type-group}'s [p].
···431 It is [None] if these invariants do not hold for [public]:
432 [1 < public < p-1] && [public <> gg]. *)
433434- val gen_group : ?g:Mirage_crypto_rng.g -> bits:int -> unit -> group
435 (** [gen_group ~g ~bits ()] generates a random {!type-group} with modulus size
436 [bits]. Uses a safe prime [p = 2q + 1] (with [q] prime) for the modulus
437 and [2] for the generator, such that [2^q = 1 mod p].
···511512 (** {1 Random generation} *)
513514- val gen : ?g:Mirage_crypto_rng.g -> Z.t -> Z.t
515 (** [gen ~g n] picks a value in the interval [\[0, n - 1\]] uniformly at random. *)
516517- val gen_r : ?g:Mirage_crypto_rng.g -> Z.t -> Z.t -> Z.t
518 (** [gen_r ~g low high] picks a value from the interval [\[low, high - 1\]]
519 uniformly at random. *)
520end
···73 (** [priv_of_primes ~e ~p ~q] is the {{!type-priv}private key} derived from the
74 minimal description [(e, p, q)]. *)
7576+ val priv_of_exp : ?g:Crypto_rng.g -> ?attempts:int -> e:Z.t -> d:Z.t ->
77 n:Z.t -> unit -> (priv, [> `Msg of string ]) result
78 (** [priv_of_exp ?g ?attempts ~e ~d n] is the unique {{!type-priv}private key}
79 characterized by the public ([e]) and private ([d]) exponents, and modulus
···95 type 'a or_digest = [ `Message of 'a | `Digest of string ]
96 (** Either an ['a] or its digest, according to some hash algorithm. *)
9798+ type mask = [ `No | `Yes | `Yes_with of Crypto_rng.g ]
99 (** Masking (cryptographic blinding) mode for the RSA transform with the
100 private key. Masking does not change the result, but it does change the
101 timing profile of the operation.
···132133 (** {1 Key generation} *)
134135+ val generate : ?g:Crypto_rng.g -> ?e:Z.t -> bits:int -> unit -> priv
136 (** [generate ~g ~e ~bits ()] is a new {{!type-priv}private key}. The new key is
137 guaranteed to be well formed, see {!val-priv}.
138···155 key size is [priv_bits key / 8], rounded up. *)
156 module PKCS1 : sig
157158+ val encrypt : ?g:Crypto_rng.g -> key:pub -> string -> string
159 (** [encrypt g key message] is a PKCS1-padded (type 2) and encrypted
160 [message].
161···227 [hlen] is the hash length. *)
228 module OAEP (H : Digestif.S) : sig
229230+ val encrypt : ?g:Crypto_rng.g -> ?label:string -> key:pub ->
231 string -> string
232 (** [encrypt ~g ~label ~key message] is {b OAEP}-padded and encrypted
233 [message], using the optional [label].
···253 hash length and [slen] is the seed length. *)
254 module PSS (H: Digestif.S) : sig
255256+ val sign : ?g:Crypto_rng.g -> ?crt_hardening:bool ->
257 ?mask:mask -> ?slen:int -> key:priv -> string or_digest -> string
258 (** [sign ~g ~crt_hardening ~mask ~slen ~key message] the [PSS]-padded
259 digest of [message], signed with the [key]. [crt_hardening] defaults
···322 L-values ([p] size) and imply the corresponding N ([q] size); The last
323 variants specifies L and N directly. *)
324325+ type mask = [ `No | `Yes | `Yes_with of Crypto_rng.g ]
326 (** Masking (cryptographic blinding) option. *)
327328 val pub_of_priv : priv -> pub
329 (** Extract the public component from a private key. *)
330331+ val generate : ?g:Crypto_rng.g -> keysize -> priv
332 (** [generate g size] is a fresh {{!type-priv}private} key. The domain parameters
333 are derived using a modified FIPS.186-4 probabilistic process, but the
334 derivation can not be validated. Note that no time masking is done for the
···416417 @raise Invalid_key if [s] is degenerate. *)
418419+ val gen_key : ?g:Crypto_rng.g -> ?bits:int -> group -> secret * string
420 (** Generate a random {!secret} and the corresponding public key.
421 [bits] is the exact bit-size of {!secret} and defaults to a value
422 dependent on the {!type-group}'s [p].
···431 It is [None] if these invariants do not hold for [public]:
432 [1 < public < p-1] && [public <> gg]. *)
433434+ val gen_group : ?g:Crypto_rng.g -> bits:int -> unit -> group
435 (** [gen_group ~g ~bits ()] generates a random {!type-group} with modulus size
436 [bits]. Uses a safe prime [p = 2q + 1] (with [q] prime) for the modulus
437 and [2] for the generator, such that [2^q = 1 mod p].
···511512 (** {1 Random generation} *)
513514+ val gen : ?g:Crypto_rng.g -> Z.t -> Z.t
515 (** [gen ~g n] picks a value in the interval [\[0, n - 1\]] uniformly at random. *)
516517+ val gen_r : ?g:Crypto_rng.g -> Z.t -> Z.t -> Z.t
518 (** [gen_r ~g low high] picks a value from the interval [\[low, high - 1\]]
519 uniformly at random. *)
520end
+7-7
pk/rsa.ml
···1-open Mirage_crypto.Uncommon
23open Common
4···150let pub_bits ({ n; _ } : pub) = Z.numbits n
151and priv_bits ({ n; _ } : priv) = Z.numbits n
152153-type mask = [ `No | `Yes | `Yes_with of Mirage_crypto_rng.g ]
154155let encrypt_unsafe ~key: ({ e; n } : pub) msg = Z.(powm msg e n)
156···206 (* XXX Generalize this into `Rng.samplev` or something. *)
207 let generate_with ?g ~f n =
208 let buf = Bytes.create n
209- and k = let b = Mirage_crypto_rng.block g in (n // b * b) in
210 let rec go nonce i j =
211 if i = n then Bytes.unsafe_to_string buf else
212- if j = k then go Mirage_crypto_rng.(generate ?g k) i 0 else
213 match String.get_uint8 nonce j with
214 | b when f b -> Bytes.set_uint8 buf i b ; go nonce (succ i) (succ j)
215 | _ -> go nonce i (succ j) in
216- go Mirage_crypto_rng.(generate ?g k) 0 0
217218 let pad ~mark ~padding k msg =
219 let pad = padding (k - String.length msg - 3 |> imax min_pad) in
···329 let max_msg_bytes k = k - 2 * hlen - 2
330331 let eme_oaep_encode ?g ?(label = "") k msg =
332- let seed = Mirage_crypto_rng.generate ?g hlen
333 and pad = String.make (max_msg_bytes k - String.length msg) '\x00' in
334 let db = String.concat "" [ H.(digest_string label |> to_raw_string) ; pad ; bx01 ; msg ] in
335 let mdb = Bytes.unsafe_to_string (MGF.mask ~seed db) in
···383384 let emsa_pss_encode ?g slen emlen msg =
385 let n = emlen // 8
386- and salt = Mirage_crypto_rng.generate ?g slen in
387 let h = digest ~salt msg in
388 let db = String.concat "" [ String.make (n - slen - hlen - 2) '\x00' ; bx01 ; salt ] in
389 let mdb = MGF.mask ~seed:h db in
···1+open Crypto.Uncommon
23open Common
4···150let pub_bits ({ n; _ } : pub) = Z.numbits n
151and priv_bits ({ n; _ } : priv) = Z.numbits n
152153+type mask = [ `No | `Yes | `Yes_with of Crypto_rng.g ]
154155let encrypt_unsafe ~key: ({ e; n } : pub) msg = Z.(powm msg e n)
156···206 (* XXX Generalize this into `Rng.samplev` or something. *)
207 let generate_with ?g ~f n =
208 let buf = Bytes.create n
209+ and k = let b = Crypto_rng.block g in (n // b * b) in
210 let rec go nonce i j =
211 if i = n then Bytes.unsafe_to_string buf else
212+ if j = k then go Crypto_rng.(generate ?g k) i 0 else
213 match String.get_uint8 nonce j with
214 | b when f b -> Bytes.set_uint8 buf i b ; go nonce (succ i) (succ j)
215 | _ -> go nonce i (succ j) in
216+ go Crypto_rng.(generate ?g k) 0 0
217218 let pad ~mark ~padding k msg =
219 let pad = padding (k - String.length msg - 3 |> imax min_pad) in
···329 let max_msg_bytes k = k - 2 * hlen - 2
330331 let eme_oaep_encode ?g ?(label = "") k msg =
332+ let seed = Crypto_rng.generate ?g hlen
333 and pad = String.make (max_msg_bytes k - String.length msg) '\x00' in
334 let db = String.concat "" [ H.(digest_string label |> to_raw_string) ; pad ; bx01 ; msg ] in
335 let mdb = Bytes.unsafe_to_string (MGF.mask ~seed db) in
···383384 let emsa_pss_encode ?g slen emlen msg =
385 let n = emlen // 8
386+ and salt = Crypto_rng.generate ?g slen in
387 let h = digest ~salt msg in
388 let db = String.concat "" [ String.make (n - slen - hlen - 2) '\x00' ; bx01 ; salt ] in
389 let mdb = MGF.mask ~seed:h db in
+7-7
pk/z_extra.ml
···1-open Mirage_crypto.Uncommon
23let bit_bound z = Z.size z * 64
4···8081let gen ?g n =
82 if n < Z.one then invalid_arg "Rng.gen: non-positive: %a" Z.pp_print n;
83- let bs = Mirage_crypto_rng.block g in
84 let bits = Z.(numbits (pred n)) in
85 let octets = bits // 8 in
86 let batch =
87- if Mirage_crypto_rng.strict g then octets else 2 * octets // bs * bs
88 in
89 let rec attempt buf =
90 if String.length buf >= octets then
91 let x = of_octets_be ~bits buf in
92 if x < n then x else attempt (String.sub buf octets (String.length buf - octets))
93- else attempt (Mirage_crypto_rng.generate ?g batch) in
94- attempt (Mirage_crypto_rng.generate ?g batch)
9596let rec gen_r ?g a b =
97- if Mirage_crypto_rng.strict g then
98 let x = gen ?g b in if x < a then gen_r ?g a b else x
99 else Z.(a + gen ?g (b - a))
100···115let gen_bits ?g ?(msb = 0) bits =
116 let bytelen = bits // 8 in
117 let buf = Bytes.create bytelen in
118- Mirage_crypto_rng.generate_into ?g buf ~off:0 bytelen;
119 set_msb msb buf ;
120 of_octets_be ~bits (Bytes.unsafe_to_string buf)
121
···1+open Crypto.Uncommon
23let bit_bound z = Z.size z * 64
4···8081let gen ?g n =
82 if n < Z.one then invalid_arg "Rng.gen: non-positive: %a" Z.pp_print n;
83+ let bs = Crypto_rng.block g in
84 let bits = Z.(numbits (pred n)) in
85 let octets = bits // 8 in
86 let batch =
87+ if Crypto_rng.strict g then octets else 2 * octets // bs * bs
88 in
89 let rec attempt buf =
90 if String.length buf >= octets then
91 let x = of_octets_be ~bits buf in
92 if x < n then x else attempt (String.sub buf octets (String.length buf - octets))
93+ else attempt (Crypto_rng.generate ?g batch) in
94+ attempt (Crypto_rng.generate ?g batch)
9596let rec gen_r ?g a b =
97+ if Crypto_rng.strict g then
98 let x = gen ?g b in if x < a then gen_r ?g a b else x
99 else Z.(a + gen ?g (b - a))
100···115let gen_bits ?g ?(msb = 0) bits =
116 let bytelen = bits // 8 in
117 let buf = Bytes.create bytelen in
118+ Crypto_rng.generate_into ?g buf ~off:0 bytelen;
119 set_msb msb buf ;
120 of_octets_be ~bits (Bytes.unsafe_to_string buf)
121
···1(* NOTE: when modifying this file, please also check whether
2 rng/miou/pfortuna.ml needs to be updated. *)
34-open Mirage_crypto
5-open Mirage_crypto.Uncommon
67module SHAd256 = struct
8 open Digestif
···1(* NOTE: when modifying this file, please also check whether
2 rng/miou/pfortuna.ml needs to be updated. *)
34+open Crypto
5+open Crypto.Uncommon
67module SHAd256 = struct
8 open Digestif
+1-1
rng/hmac_drbg.ml
···41 Bytes.unsafe_blit_string v 0 buf off H.digest_size;
42 go (off + H.digest_size) k v (pred i)
43 in
44- let v = go off g.k g.v Mirage_crypto.Uncommon.(len // H.digest_size) in
45 g.k <- H.hmac_string ~key:g.k (v ^ bx00) |> H.to_raw_string;
46 g.v <- H.hmac_string ~key:g.k v |> H.to_raw_string
47
···41 Bytes.unsafe_blit_string v 0 buf off H.digest_size;
42 go (off + H.digest_size) k v (pred i)
43 in
44+ let v = go off g.k g.v Crypto.Uncommon.(len // H.digest_size) in
45 g.k <- H.hmac_string ~key:g.k (v ^ bx00) |> H.to_raw_string;
46 g.v <- H.hmac_string ~key:g.k v |> H.to_raw_string
47
···1-open Mirage_crypto_rng
2-3-module Pfortuna = Pfortuna
4-5-type _ Effect.t += Spawn : (unit -> unit) -> unit Effect.t
6-external reraise : exn -> 'a = "%reraise"
7-8-let periodic fn delta =
9- let rec one () =
10- fn ();
11- Miou_unix.sleep (Duration.to_f delta);
12- one () in
13- Effect.perform (Spawn one)
14-15-let getrandom delta source =
16- let fn () =
17- let per_pool = 8 in
18- let size = per_pool * pools None in
19- let random = Mirage_crypto_rng_unix.getrandom size in
20- let idx = ref 0 in
21- let fn () =
22- incr idx;
23- Ok (String.sub random (per_pool * (pred !idx)) per_pool)
24- in
25- Entropy.feed_pools None source fn in
26- periodic fn delta
27-28-let getrandom_init i =
29- let data = Mirage_crypto_rng_unix.getrandom 128 in
30- Entropy.header i data
31-32-let rdrand delta =
33- match Entropy.cpu_rng with
34- | Error `Not_supported -> ()
35- | Ok cpu_rng -> periodic (cpu_rng None) delta
36-37-let running = Atomic.make false
38-39-let switch fn =
40- let orphans = Miou.orphans () in
41- let open Effect.Deep in
42- let retc = Fun.id in
43- let exnc = reraise in
44- let effc : type c. c Effect.t -> ((c, 'r) continuation -> 'r) option
45- = function
46- | Spawn fn ->
47- ignore (Miou.async ~orphans fn);
48- Some (fun k -> continue k ())
49- | _ -> None in
50- match_with fn orphans { retc; exnc; effc }
51-52-let default_generator_already_set =
53- "Mirage_crypto_rng.default_generator has already \
54- been set (but not via Mirage_crypto_rng_miou). Please check \
55- that this is intentional"
56-57-let miou_generator_already_launched =
58- "Mirage_crypto_rng_miou.initialize has already been launched \
59- and a task is already seeding the RNG."
60-61-type rng = unit Miou.t
62-63-let rec compare_and_set ?(backoff= Miou_backoff.default) t a b =
64- if Atomic.compare_and_set t a b = false
65- then compare_and_set ~backoff:(Miou_backoff.once backoff) t a b
66-67-let rec clean_up sleep orphans = match Miou.care orphans with
68- | Some None | None -> Miou_unix.sleep (Duration.to_f sleep); clean_up sleep orphans
69- | Some (Some prm) -> Miou.await_exn prm; clean_up sleep orphans
70-71-let call_if_domain_available fn =
72- let available = Miou.Domain.available () in
73- let current = (Stdlib.Domain.self () :> int) in
74- if current = 0 && available > 0
75- || current <> 0 && available > 1
76- then Miou.call fn
77- else Miou.async fn
78-79-let initialize (type a) ?g ?(sleep= Duration.of_sec 1) (rng : a generator) =
80- if Atomic.compare_and_set running false true
81- then begin
82- let seed =
83- let init = Entropy.[ bootstrap; whirlwind_bootstrap; bootstrap; getrandom_init ] in
84- List.mapi (fun i fn -> fn i) init |> String.concat "" in
85- let () =
86- try let _ = default_generator () in
87- Logs.warn (fun m -> m "%s" default_generator_already_set)
88- with No_default_generator -> () in
89- let rng = create ?g ~seed ~time:Mtime_clock.elapsed_ns rng in
90- set_default_generator rng;
91- call_if_domain_available @@ fun () -> switch @@ fun orphans ->
92- rdrand sleep;
93- let source = Entropy.register_source "getrandom" in
94- getrandom (Int64.mul sleep 10L) source;
95- clean_up sleep orphans
96- end else invalid_arg miou_generator_already_launched
97-98-let kill prm =
99- Miou.cancel prm;
100- compare_and_set running true false;
101- unset_default_generator ()
···1-(** {b RNG} seeding on {b Miou_unix}.
2-3- This module initializes a RNG with [getrandom()], and CPU RNG. On BSD system
4- (FreeBSD, OpenBSD, MacOS) [getentropy()] is used instead of [getrandom()].
5- On Windows 10 or higher, [BCryptGenRandom()] is used with the default RNG.
6- Windows 8 or lower are not supported by this library.
7-*)
8-9-module Pfortuna : Mirage_crypto_rng.Generator
10-(** {b Pfortuna}, a {b domain-safe} CSPRNG
11- {{: https://www.schneier.com/fortuna.html} proposed} by Schneier. *)
12-13-type rng
14-(** Type of tasks seeding the RNG. *)
15-16-val initialize : ?g:'a -> ?sleep:int64 -> 'a Mirage_crypto_rng.generator -> rng
17-(** [initialize ?g ?sleep (module Generator)] will allow the RNG to operate in a
18- returned task. This task periodically launches sub-tasks that seed the
19- engine (using [getrandom()], [getentropy()] or [BCryptGenRandom()] depending
20- on the system). These sub-tasks must be cleaned periodically (in seconds)
21- according to the [sleep] parameter given (defaults to 1 second).
22-23- The user must then {!val:kill} the returned task at the end of the program
24- to be sure to clean everything. Otherwise, Miou will complain with the
25- exception [Still_has_children].
26-27- We strongly recommend using {!module:Pfortuna} as an RNG engine rather than
28- {!module:Mirage_crypto_rng.Fortuna}. The engine is launched in parallel with
29- the other tasks if at least one domain is available. To ensure that there is
30- no compromise in the values generated by a {i data-race}, [Pfortuna] is an
31- {b domain-safe} implementation of Fortuna.
32-33- The user cannot make any subsequent calls to [initialize]. In other words,
34- you can only initialise a single {!type:rng} task. You must {!val:kill} the
35- returned {!type:rng} if you want to re-initialise the RNG.
36-37- A basic usage of [mirage-crypto-rng-miou-unix] is:
38- {[
39- let () = Miou_unix.run @@ fun () ->
40- let rng = Mirage_crypto_rng_miou_unix.(initialize (module Pfortuna)) in
41- let str = Mirage_crypto_rng.generate 16 in
42- Format.printf "random: %S\n%!" str;
43- Mirage_crypto_rng_miou_unix.kill rng
44- ]} *)
45-46-val kill : rng -> unit
47-(** [kill rng] terminates the {i background} task which seeds the RNG. *)
···1-(* Pfortuna is a re-implementation of Fortuna with a mutex. The goal of this
2- module is to provide a global and domain-safe RNG. The implementation use
3- [Miou.Mutex] instead of [Mutex] - [Pfortuna] is only available as part of
4- the [mirage-crypto-rng-miou-unix] package. Thus, in the context of Miou,
5- [Pfortuna] can be used and recommended in place of [Fortuna], so that the
6- user can generate random numbers in parallel in several domains.
7-8- {[
9- let () = Miou_unix.run @@ fun () ->
10- let rng = Mirage_crypto_rng_miou_unix.(initialize (module Pfortuna)) in
11- ...
12- Mirage_crypto_rng_miou_unix.kill rng
13- ]}
14-15- NOTE: when modifying this file, please also check whether rng/fortuna.ml
16- needs to be updated. *)
17-18-open Mirage_crypto
19-open Mirage_crypto.Uncommon
20-21-module SHAd256 = struct
22- open Digestif
23- type ctx = SHA256.ctx
24- let empty = SHA256.empty
25- let get t = SHA256.(get t |> to_raw_string |> digest_string |> to_raw_string)
26- let digesti i = SHA256.(digesti_string i |> to_raw_string |> digest_string |> to_raw_string)
27- let feedi = SHA256.feedi_string
28-end
29-30-let block = 16
31-32-(* the minimal amount of bytes in a pool to trigger a reseed *)
33-let min_pool_size = 64
34-(* the minimal duration between two reseeds *)
35-let min_time_duration = 1_000_000_000L
36-(* number of pools *)
37-let pools = 32
38-39-type t =
40- { ctr : AES.CTR.ctr
41- ; secret : string
42- ; key : AES.CTR.key
43- ; pools : SHAd256.ctx array
44- ; pool0_size : int
45- ; reseed_count : int
46- ; last_reseed : int64
47- ; time : (unit -> int64) option
48- }
49-50-type g = Miou.Mutex.t * t ref
51-52-let update (m, g) fn = Miou.Mutex.protect m @@ fun () -> g := fn !g
53-let get (m, g) fn = Miou.Mutex.protect m @@ fun () -> fn !g
54-55-let create ?time () =
56- let secret = String.make 32 '\000' in
57- let m = Miou.Mutex.create () in
58- let t =
59- { ctr= (0L, 0L); secret; key= AES.CTR.of_secret secret
60- ; pools= Array.make pools SHAd256.empty
61- ; pool0_size= 0
62- ; reseed_count= 0
63- ; last_reseed= 0L
64- ; time } in
65- (m, { contents= t })
66-67-let seeded ~t =
68- let lo, hi = t.ctr in
69- not (Int64.equal lo 0L && Int64.equal hi 0L)
70-71-let set_key ~t secret =
72- { t with secret; key= AES.CTR.of_secret secret }
73-74-let reseedi ~t iter =
75- let t = set_key ~t (SHAd256.digesti (fun fn -> fn t.secret; iter fn)) in
76- { t with ctr= AES.CTR.add_ctr t.ctr 1L }
77-78-let iter1 a f = f a
79-let reseed ~t cs = reseedi ~t (iter1 cs)
80-81-let generate_rekey ~t buf ~off len =
82- let b = len // block* 2 in
83- let n = b * block in
84- let r = AES.CTR.stream ~key:t.key ~ctr:t.ctr n in
85- Bytes.unsafe_blit_string r 0 buf off len;
86- let r2 = String.sub r (n - 32) 32 in
87- let t = set_key ~t r2 in
88- { t with ctr= AES.CTR.add_ctr t.ctr (Int64.of_int b) }
89-90-let add_pool_entropy t =
91- if t.pool0_size > min_pool_size then
92- let should_reseed, now = match t.time with
93- | None -> true, 0L
94- | Some fn ->
95- let now = fn () in
96- Int64.(sub now t.last_reseed > min_time_duration), now in
97- if should_reseed then begin
98- let t = { t with reseed_count= t.reseed_count + 1
99- ; last_reseed= now
100- ; pool0_size= 0 } in
101- reseedi ~t @@ fun add ->
102- for i = 0 to pools - 1 do
103- if t.reseed_count land ((1 lsl i) - 1) = 0
104- then (SHAd256.get t.pools.(i) |> add; t.pools.(i) <- SHAd256.empty)
105- done
106- end else t else t
107-108-let generate_into ~t buf ~off len =
109- let t = add_pool_entropy t in
110- if not (seeded ~t) then raise Mirage_crypto_rng.Unseeded_generator;
111- let rec chunk t off = function
112- | i when i <= 0 -> t
113- | n ->
114- let n' = imin n 0x10000 in
115- let t = generate_rekey ~t buf ~off n' in
116- chunk t (off + n') (n - n') in
117- chunk t off len
118-119-let add ~t source ~pool data =
120- let buf = Bytes.create 2
121- and pool = pool land (pools - 1)
122- and source = Mirage_crypto_rng.Entropy.id source land 0xff in
123- Bytes.set_uint8 buf 0 source;
124- Bytes.set_uint8 buf 1 (String.length data);
125- t.pools.(pool) <- SHAd256.feedi t.pools.(pool) (iter2 (Bytes.unsafe_to_string buf) data);
126- if pool = 0 then { t with pool0_size= t.pool0_size + String.length data } else t
127-128-let accumulate ~g source =
129- let pool = ref 0 in
130- `Acc (fun buf ->
131- update g @@ fun t ->
132- let t = add ~t source ~pool:!pool buf in
133- incr pool; t)
134-135-let reseed ~g cs = update g @@ fun t -> reseed ~t cs
136-let generate_into ~g buf ~off len = update g @@ fun t -> generate_into ~t buf ~off len
137-let seeded ~g = get g @@ fun t -> seeded ~t
···1-(*
2- * Copyright (c) 2014 Hannes Mehnert
3- * Copyright (c) 2014 Anil Madhavapeddy <anil@recoil.org>
4- * Copyright (c) 2014-2016 David Kaloper Meršinjak
5- * Copyright (c) 2015 Citrix Systems Inc
6- * All rights reserved.
7- *
8- * Redistribution and use in source and binary forms, with or without
9- * modification, are permitted provided that the following conditions are met:
10- *
11- * * Redistributions of source code must retain the above copyright notice, this
12- * list of conditions and the following disclaimer.
13- *
14- * * Redistributions in binary form must reproduce the above copyright notice,
15- * this list of conditions and the following disclaimer in the documentation
16- * and/or other materials provided with the distribution.
17- *
18- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28- *)
29-30-let src = Logs.Src.create "mirage-crypto-rng-mirage" ~doc:"Mirage crypto RNG mirage"
31-module Log = (val Logs.src_log src : Logs.LOG)
32-33-open Mirage_crypto_rng
34-35-let rdrand_task delta =
36- match Entropy.cpu_rng with
37- | Error `Not_supported -> ()
38- | Ok cpu_rng ->
39- let open Lwt.Infix in
40- let rdrand = cpu_rng None in
41- Lwt.async (fun () ->
42- let rec one () =
43- rdrand ();
44- Mirage_sleep.ns delta >>=
45- one
46- in
47- one ())
48-49-let bootstrap_functions () =
50- Entropy.[ bootstrap ; bootstrap ; whirlwind_bootstrap ; bootstrap ]
51-52-let running = ref false
53-54-let initialize (type a) ?g ?(sleep = Duration.of_sec 1) (rng : a generator) =
55- if !running then
56- Lwt.fail_with "entropy collection already running"
57- else begin
58- (try
59- let _ = default_generator () in
60- Log.warn (fun m -> m "Mirage_crypto_rng.default_generator has already \
61- been set, check that this call is intentional");
62- with
63- No_default_generator -> ());
64- running := true;
65- let seed =
66- List.mapi (fun i f -> f i) (bootstrap_functions ()) |> String.concat ""
67- in
68- let rng = create ?g ~seed ~time:Mirage_mtime.elapsed_ns rng in
69- set_default_generator rng;
70- rdrand_task sleep;
71- Mirage_runtime.at_enter_iter (Entropy.timer_accumulator None);
72- Lwt.return_unit
73- end
···1-(*
2- * Copyright (c) 2014 Hannes Mehnert
3- * Copyright (c) 2014 Anil Madhavapeddy <anil@recoil.org>
4- * Copyright (c) 2014-2016 David Kaloper Meršinjak
5- * All rights reserved.
6- *
7- * Redistribution and use in source and binary forms, with or without
8- * modification, are permitted provided that the following conditions are met:
9- *
10- * * Redistributions of source code must retain the above copyright notice, this
11- * list of conditions and the following disclaimer.
12- *
13- * * Redistributions in binary form must reproduce the above copyright notice,
14- * this list of conditions and the following disclaimer in the documentation
15- * and/or other materials provided with the distribution.
16- *
17- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27- *)
28-29-val initialize :
30- ?g:'a -> ?sleep:int64 -> 'a Mirage_crypto_rng.generator -> unit Lwt.t
31-(** [initialize ~g ~sleep generator] sets the default generator to the
32- [generator] and sets up periodic entropy feeding for that rng. This
33- function fails ([Lwt.fail]) if it is called a second time. The argument
34- [~sleep] is measured in ns, and used as sleep between cpu assisted random
35- number collection. It defaults to one second. *)
···00000000000000000000000000000000000
rng/mirage_crypto_rng.ml
rng/crypto_rng.ml
+8-8
rng/mirage_crypto_rng.mli
rng/crypto_rng.mli
···20 library, you can use /dev/urandom or getentropy(3) (actually getrandom(3) on
21 Linux, getentropy() on macOS and BSD systems, BCryptGenRandom on Windows).
2223- Please ensure to call [Mirage_crypto_rng_unix.use_default], or
24- [Mirage_crypto_rng_unix.use_dev_urandom] (if you only want to use
25- /dev/urandom), or [Mirage_crypto_rng_unix.use_getentropy] (if you only want
26 to use getrandom/getentropy/BCryptGenRandom).
2728 For fine-grained control (doing entropy harvesting, etc.), please continue
···31 via Pfortuna).
3233 Suitable entropy feeding of generators are provided by other libraries
34- {{!Mirage_crypto_rng_mirage}mirage-crypto-rng-mirage} (for MirageOS),
35- and {{!Mirage_crypto_rng_miou_unix}mirage-crypto-miou-unix} (for Miou_unix).
3637 The intention is that "initialize" in the respective sub-library is called
38 once, which sets the default generator and registers entropy
···176 (** Create a new, unseeded {{!g}g}. *)
177178 val generate_into : g:g -> bytes -> off:int -> int -> unit
179- [@@alert unsafe "Does not do bounds checks. Use Mirage_crypto_rng.generate_into instead."]
180 (** [generate_into ~g buf ~off n] produces [n] uniformly distributed random
181 bytes into [buf] at offset [off], updating the state of [g].
182183 Assumes that [buf] is at least [off + n] bytes long. Also assumes that
184 [off] and [n] are positive integers. Caution: do not use in your
185- application, use [Mirage_crypto_rng.generate_into] instead.
186 *)
187188 val reseed : g:g -> string -> unit
···294 if i < 1 then [] else Rng.generate ?g n :: f1 ?g ~n (i - 1)]}
295296 Generating a [Z.t] smaller than [10]:
297-{[let f2 ?g () = Mirage_crypto_pk.Z_extra.gen ?g Z.(~$10)]}
298299 Creating a local Fortuna instance and using it as a key-derivation function:
300{[let f3 secret =
···20 library, you can use /dev/urandom or getentropy(3) (actually getrandom(3) on
21 Linux, getentropy() on macOS and BSD systems, BCryptGenRandom on Windows).
2223+ Please ensure to call [Crypto_rng_unix.use_default], or
24+ [Crypto_rng_unix.use_dev_urandom] (if you only want to use
25+ /dev/urandom), or [Crypto_rng_unix.use_getentropy] (if you only want
26 to use getrandom/getentropy/BCryptGenRandom).
2728 For fine-grained control (doing entropy harvesting, etc.), please continue
···31 via Pfortuna).
3233 Suitable entropy feeding of generators are provided by other libraries
34+ {{!Crypto_rng_mirage}mirage-crypto-rng-mirage} (for MirageOS),
35+ and {{!Crypto_rng_miou_unix}mirage-crypto-miou-unix} (for Miou_unix).
3637 The intention is that "initialize" in the respective sub-library is called
38 once, which sets the default generator and registers entropy
···176 (** Create a new, unseeded {{!g}g}. *)
177178 val generate_into : g:g -> bytes -> off:int -> int -> unit
179+ [@@alert unsafe "Does not do bounds checks. Use Crypto_rng.generate_into instead."]
180 (** [generate_into ~g buf ~off n] produces [n] uniformly distributed random
181 bytes into [buf] at offset [off], updating the state of [g].
182183 Assumes that [buf] is at least [off + n] bytes long. Also assumes that
184 [off] and [n] are positive integers. Caution: do not use in your
185+ application, use [Crypto_rng.generate_into] instead.
186 *)
187188 val reseed : g:g -> string -> unit
···294 if i < 1 then [] else Rng.generate ?g n :: f1 ?g ~n (i - 1)]}
295296 Generating a [Z.t] smaller than [10]:
297+{[let f2 ?g () = Crypto_pk.Z_extra.gen ?g Z.(~$10)]}
298299 Creating a local Fortuna instance and using it as a key-derivation function:
300{[let f3 secret =
+3-3
rng/rng.ml
···67let setup_rng =
8 "\nPlease setup your default random number generator. On Unix, the best \
9- path is to call [Mirage_crypto_rng_unix.use_default ()].\
10 \nBut you can use Fortuna (or any other RNG) and setup the seeding \
11 (done by default in MirageOS): \
12 \n\
···17 `let main = Mirage.main \"Unikernel.Main\" (random @-> job)`, \
18 and `let () = register \"my_unikernel\" [main $ default_random]`. \
19 \n If you are using miou, execute \
20- `Mirage_crypto_rng_miou_unix.initialize (module Mirage_crypto_rng.Fortuna)` \
21 at startup."
2223let () = Printexc.register_printer (function
···32 val block : int
33 val create : ?time:(unit -> int64) -> unit -> g
34 val generate_into : g:g -> bytes -> off:int -> int -> unit
35- [@@alert unsafe "Does not do bounds checks. Use Mirage_crypto_rng.generate_into instead."]
36 val reseed : g:g -> string -> unit
37 val accumulate : g:g -> source -> [`Acc of string -> unit]
38 val seeded : g:g -> bool
···67let setup_rng =
8 "\nPlease setup your default random number generator. On Unix, the best \
9+ path is to call [Crypto_rng_unix.use_default ()].\
10 \nBut you can use Fortuna (or any other RNG) and setup the seeding \
11 (done by default in MirageOS): \
12 \n\
···17 `let main = Mirage.main \"Unikernel.Main\" (random @-> job)`, \
18 and `let () = register \"my_unikernel\" [main $ default_random]`. \
19 \n If you are using miou, execute \
20+ `Crypto_rng_miou_unix.initialize (module Crypto_rng.Fortuna)` \
21 at startup."
2223let () = Printexc.register_printer (function
···32 val block : int
33 val create : ?time:(unit -> int64) -> unit -> g
34 val generate_into : g:g -> bytes -> off:int -> int -> unit
35+ [@@alert unsafe "Does not do bounds checks. Use Crypto_rng.generate_into instead."]
36 val reseed : g:g -> string -> unit
37 val accumulate : g:g -> source -> [`Acc of string -> unit]
38 val seeded : g:g -> bool
···1-open Mirage_crypto_rng
23module Urandom = Urandom
4···1415let use_default () = use_getentropy ()
1617-let src = Logs.Src.create "mirage-crypto-rng.unix" ~doc:"Mirage crypto RNG Unix"
18module Log = (val Logs.src_log src : Logs.LOG)
1920external getrandom_buf : bytes -> int -> int -> unit = "mc_getrandom" [@@noalloc]
···36let initialize (type a) ?g (rng : a generator) =
37 if Atomic.get running then
38 Log.debug
39- (fun m -> m "Mirage_crypto_rng_unix.initialize has already been called, \
40 ignoring this call.")
41 else begin
42 (try
43 let _ = default_generator () in
44- Log.warn (fun m -> m "Mirage_crypto_rng.default_generator has already \
45 been set, check that this call is intentional");
46 with
47 No_default_generator -> ());
···1+open Crypto_rng
23module Urandom = Urandom
4···1415let use_default () = use_getentropy ()
1617+let src = Logs.Src.create "crypto-rng.unix" ~doc:"Mirage crypto RNG Unix"
18module Log = (val Logs.src_log src : Logs.LOG)
1920external getrandom_buf : bytes -> int -> int -> unit = "mc_getrandom" [@@noalloc]
···36let initialize (type a) ?g (rng : a generator) =
37 if Atomic.get running then
38 Log.debug
39+ (fun m -> m "Crypto_rng_unix.initialize has already been called, \
40 ignoring this call.")
41 else begin
42 (try
43 let _ = default_generator () in
44+ Log.warn (fun m -> m "Crypto_rng.default_generator has already \
45 been set, check that this call is intentional");
46 with
47 No_default_generator -> ());
···7*)
89(** [initialize ~g rng] will bring the RNG into a working state. *)
10-val initialize : ?g:'a -> 'a Mirage_crypto_rng.generator -> unit
11-[@@deprecated "Use 'Mirage_crypto_rng_unix.use_default ()' instead."]
1213(** [getrandom size] returns a buffer of [size] filled with random bytes. *)
14val getrandom : int -> string
···16(** A generator that opens /dev/urandom and reads from that file descriptor
17 data whenever random data is needed. The file descriptor is closed in
18 [at_exit]. *)
19-module Urandom : Mirage_crypto_rng.Generator
2021(** A generator using [getrandom(3)] on Linux, [getentropy(3)] on BSD and macOS,
22 and [BCryptGenRandom()] on Windows. *)
23-module Getentropy : Mirage_crypto_rng.Generator
2425-(** [use_default ()] initializes the RNG [Mirage_crypto_rng.default_generator]
26 with a sensible default, at the moment using [Getentropy]. *)
27val use_default : unit -> unit
2829(** [use_dev_random ()] initializes the RNG
30- [Mirage_crypto_rng.default_generator] with the [Urandom] generator. This
31 raises an exception if "/dev/urandom" cannot be opened. *)
32val use_dev_urandom : unit -> unit
3334-(** [use_getentropy ()] initializes the RNG [Mirage_crypto_rng.default_generator]
35 with the [Getentropy] generator. *)
36val use_getentropy : unit -> unit
···7*)
89(** [initialize ~g rng] will bring the RNG into a working state. *)
10+val initialize : ?g:'a -> 'a Crypto_rng.generator -> unit
11+[@@deprecated "Use 'Crypto_rng_unix.use_default ()' instead."]
1213(** [getrandom size] returns a buffer of [size] filled with random bytes. *)
14val getrandom : int -> string
···16(** A generator that opens /dev/urandom and reads from that file descriptor
17 data whenever random data is needed. The file descriptor is closed in
18 [at_exit]. *)
19+module Urandom : Crypto_rng.Generator
2021(** A generator using [getrandom(3)] on Linux, [getentropy(3)] on BSD and macOS,
22 and [BCryptGenRandom()] on Windows. *)
23+module Getentropy : Crypto_rng.Generator
2425+(** [use_default ()] initializes the RNG [Crypto_rng.default_generator]
26 with a sensible default, at the moment using [Getentropy]. *)
27val use_default : unit -> unit
2829(** [use_dev_random ()] initializes the RNG
30+ [Crypto_rng.default_generator] with the [Urandom] generator. This
31 raises an exception if "/dev/urandom" cannot be opened. *)
32val use_dev_urandom : unit -> unit
3334+(** [use_getentropy ()] initializes the RNG [Crypto_rng.default_generator]
35 with the [Getentropy] generator. *)
36val use_getentropy : unit -> unit
···1/* Based on https://github.com/abeaumont/ocaml-chacha.git */
23-#include "mirage_crypto.h"
45extern void mc_chacha_core_generic(int count, const uint32_t *src, uint32_t *dst);
6
···1/* Based on https://github.com/abeaumont/ocaml-chacha.git */
23+#include "crypto.h"
45extern void mc_chacha_core_generic(int count, const uint32_t *src, uint32_t *dst);
6
+1-1
src/native/chacha_generic.c
···1/* Based on https://github.com/abeaumont/ocaml-chacha.git */
23-#include "mirage_crypto.h"
45static inline void mc_chacha_quarterround(uint32_t *x, int a, int b, int c, int d) {
6 x[a] += x[b]; x[d] = rol32(x[d] ^ x[a], 16);
···1/* Based on https://github.com/abeaumont/ocaml-chacha.git */
23+#include "crypto.h"
45static inline void mc_chacha_quarterround(uint32_t *x, int a, int b, int c, int d) {
6 x[a] += x[b]; x[d] = rol32(x[d] ^ x[a], 16);
···67#include <caml/mlvalues.h>
89-#include "mirage_crypto.h"
1011#if defined (__i386__) || defined (__x86_64__)
12#include <x86intrin.h>
···67#include <caml/mlvalues.h>
89+#include "crypto.h"
1011#if defined (__i386__) || defined (__x86_64__)
12#include <x86intrin.h>
+1-1
src/native/ghash_ctmul.c
···36 * worth the effort.
37 */
3839-#include "mirage_crypto.h"
40#include <string.h>
4142/* Microsoft compiler does not support 128-bit integers. Drop down to
···36 * worth the effort.
37 */
3839+#include "crypto.h"
40#include <string.h>
4142/* Microsoft compiler does not support 128-bit integers. Drop down to
+1-1
src/native/ghash_generic.c
···1/* Copyright (c) 2017 David Kaloper Meršinjak. All rights reserved.
2 See LICENSE.md. */
34-#include "mirage_crypto.h"
5#include <string.h>
67/* Generic table-driven GHASH.
···1/* Copyright (c) 2017 David Kaloper Meršinjak. All rights reserved.
2 See LICENSE.md. */
34+#include "crypto.h"
5#include <string.h>
67/* Generic table-driven GHASH.
···2let data = ref ""
34let cpu_bootstrap_check () =
5- match Mirage_crypto_rng.Entropy.cpu_rng_bootstrap with
6 | Error `Not_supported -> print_endline "no CPU RNG available"
7 | Ok cpu_rng_bootstrap ->
8 match cpu_rng_bootstrap 1 with
···2223let whirlwind_bootstrap_check () =
24 for i = 0 to 10 do
25- let data' = Mirage_crypto_rng.Entropy.whirlwind_bootstrap 1 in
26 if String.equal !data data' then begin
27 Ohex.pp Format.std_formatter data';
28 failwith ("same data from whirlwind bootstrap at " ^ string_of_int i);
···3233let timer_check () =
34 for i = 0 to 10 do
35- let data' = Mirage_crypto_rng.Entropy.interrupt_hook () in
36 if String.equal !data data' then begin
37 Ohex.pp Format.std_formatter data';
38 failwith ("same data from timer at " ^ string_of_int i);
···2let data = ref ""
34let cpu_bootstrap_check () =
5+ match Crypto_rng.Entropy.cpu_rng_bootstrap with
6 | Error `Not_supported -> print_endline "no CPU RNG available"
7 | Ok cpu_rng_bootstrap ->
8 match cpu_rng_bootstrap 1 with
···2223let whirlwind_bootstrap_check () =
24 for i = 0 to 10 do
25+ let data' = Crypto_rng.Entropy.whirlwind_bootstrap 1 in
26 if String.equal !data data' then begin
27 Ohex.pp Format.std_formatter data';
28 failwith ("same data from whirlwind bootstrap at " ^ string_of_int i);
···3233let timer_check () =
34 for i = 0 to 10 do
35+ let data' = Crypto_rng.Entropy.interrupt_hook () in
36 if String.equal !data data' then begin
37 Ohex.pp Format.std_formatter data';
38 failwith ("same data from timer at " ^ string_of_int i);
-36
tests/test_entropy_collection.ml
···1-open Lwt.Infix
2-3-module Printing_rng = struct
4- type g = unit
5-6- let block = 16
7-8- let create ?time:_ () = ()
9-10- let generate_into ~g:_ _buf ~off:_ _len = assert false
11-12- let reseed ~g:_ data =
13- Format.printf "reseeding:@.%a@.%!" (Ohex.pp_hexdump ()) data
14-15- let accumulate ~g:_ source =
16- let print data =
17- Format.printf "accumulate: (src: %a) %a@.%!"
18- Mirage_crypto_rng.Entropy.pp_source source Ohex.pp data
19- in
20- `Acc print
21-22- let seeded ~g:_ = true
23- let pools = 1
24-end
25-26-let with_entropy act =
27- Mirage_crypto_rng_mirage.initialize (module Printing_rng) >>= fun () ->
28- Format.printf "entropy sources: %a@,%!"
29- (fun ppf -> List.iter (fun x ->
30- Mirage_crypto_rng.Entropy.pp_source ppf x;
31- Format.pp_print_space ppf ()))
32- (Mirage_crypto_rng.Entropy.sources ());
33- act ()
34-35-let () =
36- Unix_os.(Main.run (with_entropy (fun () -> Time.sleep_ns (Duration.of_sec 3))))
···000000000000000000000000000000000000
-31
tests/test_miou_entropy_collection.ml
···1-module Printing_rng = struct
2- type g = unit
3-4- let block = 16
5- let create ?time:_ () = ()
6- let generate_into ~g:_ _buf ~off:_ _len = assert false
7- let seeded ~g:_ = true
8- let pools = 1
9-10- let reseed ~g:_ data =
11- Format.printf "reseeding:@.%a@.%!" (Ohex.pp_hexdump ()) data
12-13- let accumulate ~g:_ source =
14- let print data =
15- Format.printf "accumulate: (src: %a) %a@.%!"
16- Mirage_crypto_rng.Entropy.pp_source source Ohex.pp data
17- in
18- `Acc print
19-end
20-21-let () =
22- Miou_unix.run @@ fun () ->
23- let rng = Mirage_crypto_rng_miou_unix.initialize (module Printing_rng) in
24- Format.printf "entropy sources: %a@,%!"
25- (fun ppf -> List.iter (fun x ->
26- Mirage_crypto_rng.Entropy.pp_source ppf x;
27- Format.pp_print_space ppf ()))
28- (Mirage_crypto_rng.Entropy.sources ());
29- let sleep = Duration.(of_sec 2 |> to_f) in
30- Miou_unix.sleep sleep;
31- Mirage_crypto_rng_miou_unix.kill rng
···0000000000000000000000000000000
-16
tests/test_miou_rng.ml
···1-let () = Miou_unix.run @@ fun () ->
2- let rng = Mirage_crypto_rng_miou_unix.(initialize (module Pfortuna)) in
3- let random_num = Mirage_crypto_rng.generate 32 in
4- assert (String.length random_num = 32);
5- Printf.printf "32 bit random number: %s\n%!" (Ohex.encode random_num);
6- let random_num = Mirage_crypto_rng.generate 16 in
7- assert (String.length random_num = 16);
8- Printf.printf "16 bit random number: %s\n%!" (Ohex.encode random_num);
9- (* NOTE(dinosaure): the test below shows that [Pfortuna] is domain-safe when
10- run with TSan. If we use the Fortuna engine, TSan will report invalid
11- accesses between the domain that seeds the RNG and [dom0]. *)
12- for _ = 0 to 4 do
13- let _ = Mirage_crypto_rng.generate 16 in
14- Miou_unix.sleep 0.5;
15- done;
16- Mirage_crypto_rng_miou_unix.kill rng
···0000000000000000
+3-3
tests/test_numeric.ml
···1open OUnit2
23-open Mirage_crypto.Uncommon
4-open Mirage_crypto_pk
56open Test_common
7···1516let n_decode_reencode_selftest ~typ ~bytes n =
17 typ ^ " selftest" >:: times ~n @@ fun _ ->
18- let cs = Mirage_crypto_rng.generate bytes in
19 let cs' = Z_extra.(to_octets_be ~size:bytes @@ of_octets_be cs) in
20 assert_oct_equal cs cs'
21
···1open OUnit2
23+open Crypto.Uncommon
4+open Crypto_pk
56open Test_common
7···1516let n_decode_reencode_selftest ~typ ~bytes n =
17 typ ^ " selftest" >:: times ~n @@ fun _ ->
18+ let cs = Crypto_rng.generate bytes in
19 let cs' = Z_extra.(to_octets_be ~size:bytes @@ of_octets_be cs) in
20 assert_oct_equal cs cs'
21
···1open OUnit2
23-open Mirage_crypto
45open Test_common
67let sample arr =
8 let ix =
9- Randomconv.int ~bound:(Array.length arr) Mirage_crypto_rng.generate
10 in
11 arr.(ix)
12···15let ecb_selftest (m : (module Block.ECB)) n =
16 let module C = ( val m ) in
17 "selftest" >:: times ~n @@ fun _ ->
18- let data = Mirage_crypto_rng.generate (C.block_size * 8)
19- and key = C.of_secret @@ Mirage_crypto_rng.generate (sample C.key_sizes) in
20 let data' =
21 C.( data |> encrypt ~key |> encrypt ~key
22 |> decrypt ~key |> decrypt ~key ) in
···25let cbc_selftest (m : (module Block.CBC)) n =
26 let module C = ( val m ) in
27 "selftest" >:: times ~n @@ fun _ ->
28- let data = Mirage_crypto_rng.generate (C.block_size * 8)
29- and iv = Mirage_crypto_rng.generate C.block_size
30- and key = C.of_secret @@ Mirage_crypto_rng.generate (sample C.key_sizes) in
31 assert_oct_equal ~msg:"CBC e->e->d->d" data
32 C.( data |> encrypt ~key ~iv |> encrypt ~key ~iv
33 |> decrypt ~key ~iv |> decrypt ~key ~iv );
···44 let module M = (val m) in
45 let bs = M.block_size in
46 "selftest" >:: times ~n @@ fun _ ->
47- let key = M.of_secret @@ Mirage_crypto_rng.generate (sample M.key_sizes)
48- and ctr = Mirage_crypto_rng.generate bs |> M.ctr_of_octets
49- and data = Mirage_crypto_rng.(generate @@ bs + Randomconv.int ~bound:(20 * bs) Mirage_crypto_rng.generate) in
50 let enc = M.encrypt ~key ~ctr data in
51 let dec = M.decrypt ~key ~ctr enc in
52 assert_oct_equal ~msg:"CTR e->d" data dec;
53 let (d1, d2) =
54- let s = bs * Randomconv.int ~bound:(String.length data / bs) Mirage_crypto_rng.generate in
55 String.sub data 0 s, String.sub data s (String.length data - s)
56 in
57 assert_oct_equal ~msg:"CTR chain" enc @@
···60let ctr_offsets (type c) ~zero (m : (module Block.CTR with type ctr = c)) n =
61 let module M = (val m) in
62 "offsets" >:: fun _ ->
63- let key = M.of_secret @@ Mirage_crypto_rng.generate M.key_sizes.(0) in
64 for i = 0 to n - 1 do
65 let ctr = match i with
66 | 0 -> M.add_ctr zero (-1L)
67- | _ -> Mirage_crypto_rng.generate M.block_size |> M.ctr_of_octets
68- and gap = Randomconv.int ~bound:64 Mirage_crypto_rng.generate in
69 let s1 = M.stream ~key ~ctr ((gap + 1) * M.block_size)
70 and s2 = M.stream ~key ~ctr:(M.add_ctr ctr (Int64.of_int gap)) M.block_size in
71 assert_oct_equal ~msg:"shifted stream"
···75let xor_selftest n =
76 "selftest" >:: times ~n @@ fun _ ->
7778- let n = Randomconv.int ~bound:30 Mirage_crypto_rng.generate in
79- let (x, y, z) = Mirage_crypto_rng.(generate n, generate n, generate n) in
8081 let xyz = Uncommon.(xor (xor x y) z)
82 and xyz' = Uncommon.(xor x (xor y z)) in
···105 ]
106107let () =
108- Mirage_crypto_rng_unix.use_default ();
109 run_test_tt_main suite
···1open OUnit2
23+open Crypto
45open Test_common
67let sample arr =
8 let ix =
9+ Randomconv.int ~bound:(Array.length arr) Crypto_rng.generate
10 in
11 arr.(ix)
12···15let ecb_selftest (m : (module Block.ECB)) n =
16 let module C = ( val m ) in
17 "selftest" >:: times ~n @@ fun _ ->
18+ let data = Crypto_rng.generate (C.block_size * 8)
19+ and key = C.of_secret @@ Crypto_rng.generate (sample C.key_sizes) in
20 let data' =
21 C.( data |> encrypt ~key |> encrypt ~key
22 |> decrypt ~key |> decrypt ~key ) in
···25let cbc_selftest (m : (module Block.CBC)) n =
26 let module C = ( val m ) in
27 "selftest" >:: times ~n @@ fun _ ->
28+ let data = Crypto_rng.generate (C.block_size * 8)
29+ and iv = Crypto_rng.generate C.block_size
30+ and key = C.of_secret @@ Crypto_rng.generate (sample C.key_sizes) in
31 assert_oct_equal ~msg:"CBC e->e->d->d" data
32 C.( data |> encrypt ~key ~iv |> encrypt ~key ~iv
33 |> decrypt ~key ~iv |> decrypt ~key ~iv );
···44 let module M = (val m) in
45 let bs = M.block_size in
46 "selftest" >:: times ~n @@ fun _ ->
47+ let key = M.of_secret @@ Crypto_rng.generate (sample M.key_sizes)
48+ and ctr = Crypto_rng.generate bs |> M.ctr_of_octets
49+ and data = Crypto_rng.(generate @@ bs + Randomconv.int ~bound:(20 * bs) Crypto_rng.generate) in
50 let enc = M.encrypt ~key ~ctr data in
51 let dec = M.decrypt ~key ~ctr enc in
52 assert_oct_equal ~msg:"CTR e->d" data dec;
53 let (d1, d2) =
54+ let s = bs * Randomconv.int ~bound:(String.length data / bs) Crypto_rng.generate in
55 String.sub data 0 s, String.sub data s (String.length data - s)
56 in
57 assert_oct_equal ~msg:"CTR chain" enc @@
···60let ctr_offsets (type c) ~zero (m : (module Block.CTR with type ctr = c)) n =
61 let module M = (val m) in
62 "offsets" >:: fun _ ->
63+ let key = M.of_secret @@ Crypto_rng.generate M.key_sizes.(0) in
64 for i = 0 to n - 1 do
65 let ctr = match i with
66 | 0 -> M.add_ctr zero (-1L)
67+ | _ -> Crypto_rng.generate M.block_size |> M.ctr_of_octets
68+ and gap = Randomconv.int ~bound:64 Crypto_rng.generate in
69 let s1 = M.stream ~key ~ctr ((gap + 1) * M.block_size)
70 and s2 = M.stream ~key ~ctr:(M.add_ctr ctr (Int64.of_int gap)) M.block_size in
71 assert_oct_equal ~msg:"shifted stream"
···75let xor_selftest n =
76 "selftest" >:: times ~n @@ fun _ ->
7778+ let n = Randomconv.int ~bound:30 Crypto_rng.generate in
79+ let (x, y, z) = Crypto_rng.(generate n, generate n, generate n) in
8081 let xyz = Uncommon.(xor (xor x y) z)
82 and xyz' = Uncommon.(xor x (xor y z)) in
···105 ]
106107let () =
108+ Crypto_rng_unix.use_default ();
109 run_test_tt_main suite
+14-14
tests/test_rsa.ml
···1open OUnit2
23-open Mirage_crypto.Uncommon
4-open Mirage_crypto_pk
56open Test_common
7···19 try
20 Bytes.blit_string !g 0 buf off n;
21 g := String.sub !g n (String.length !g - n)
22- with Invalid_argument _ -> raise Mirage_crypto_rng.Unseeded_generator
2324 let reseed ~g buf = g := !g ^ buf
25···31end
3233let random_is seed =
34- Mirage_crypto_rng.create ~seed:seed (module Null)
3536let gen_rsa ~bits =
37 let e = Z.(if bits < 24 then ~$3 else ~$0x10001) in
···83 let msg =
84 let size = bits // 8 in
85 let buf = Bytes.create size in
86- Mirage_crypto_rng.generate_into buf ~off:0 size;
87- let i = 1 + Randomconv.int ~bound:(pred size) Mirage_crypto_rng.generate in
88 Bytes.set_uint8 buf 0 0;
89 Bytes.(set_uint8 buf i (get_uint8 buf i lor 2));
90 Bytes.unsafe_to_string buf
···103let pkcs_message_for_bits bits =
104 let padding = 12 in
105 let size = bits // 8 - padding in
106- assert (size >= 0) ; Mirage_crypto_rng.generate size
107108let rsa_pkcs1_encode_selftest ~bits n =
109 "selftest" >:: times ~n @@ fun _ ->
···119 let open Digestif.SHA1 in
120 "selftest" >:: times ~n @@ fun _ ->
121 let key = gen_rsa ~bits:(Rsa.PKCS1.min_key `SHA1)
122- and msg = Mirage_crypto_rng.generate 47 in
123 let pkey = Rsa.pub_of_priv key in
124 assert_bool "invert 1" Rsa.PKCS1.(
125 verify ~key:pkey ~hashp:any (`Message msg)
···146 let module OAEP_SHA384 = Rsa.OAEP (Digestif.SHA384) in
147 "selftest" >:: times ~n @@ fun _ ->
148 let key = gen_rsa ~bits in
149- let msg = Mirage_crypto_rng.generate (bits // 8 - 2 * Digestif.MD5.digest_size - 2) in
150 let enc = OAEP_MD5.encrypt ~key:(Rsa.pub_of_priv key) msg in
151 (match OAEP_MD5.decrypt ~key enc with
152 | None -> assert_failure "unpad failure"
153 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
154- let msg = Mirage_crypto_rng.generate (bits // 8 - 2 * Digestif.SHA1.digest_size - 2) in
155 let enc = OAEP_SHA1.encrypt ~key:(Rsa.pub_of_priv key) msg in
156 (match OAEP_SHA1.decrypt ~key enc with
157 | None -> assert_failure "unpad failure"
158 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
159- let msg = Mirage_crypto_rng.generate (bits // 8 - 2 * Digestif.SHA224.digest_size - 2) in
160 let enc = OAEP_SHA224.encrypt ~key:(Rsa.pub_of_priv key) msg in
161 (match OAEP_SHA224.decrypt ~key enc with
162 | None -> assert_failure "unpad failure"
163 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
164- let msg = Mirage_crypto_rng.generate (bits // 8 - 2 * Digestif.SHA256.digest_size - 2) in
165 let enc = OAEP_SHA256.encrypt ~key:(Rsa.pub_of_priv key) msg in
166 (match OAEP_SHA256.decrypt ~key enc with
167 | None -> assert_failure "unpad failure"
168 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
169- let msg = Mirage_crypto_rng.generate (bits // 8 - 2 * Digestif.SHA384.digest_size - 2) in
170 let enc = OAEP_SHA384.encrypt ~key:(Rsa.pub_of_priv key) msg in
171 (match OAEP_SHA384.decrypt ~key enc with
172 | None -> assert_failure "unpad failure"
···176 let module Pss_sha1 = Rsa.PSS (Digestif.SHA1) in
177 "selftest" >:: times ~n @@ fun _ ->
178 let key = gen_rsa ~bits
179- and msg = Mirage_crypto_rng.generate 1024 in
180 let pkey = Rsa.pub_of_priv key in
181 let dgst = Digestif.SHA1.(digest_string msg |> to_raw_string) in
182 let signature = Pss_sha1.sign ~key (`Digest dgst) in
···1open OUnit2
23+open Crypto.Uncommon
4+open Crypto_pk
56open Test_common
7···19 try
20 Bytes.blit_string !g 0 buf off n;
21 g := String.sub !g n (String.length !g - n)
22+ with Invalid_argument _ -> raise Crypto_rng.Unseeded_generator
2324 let reseed ~g buf = g := !g ^ buf
25···31end
3233let random_is seed =
34+ Crypto_rng.create ~seed:seed (module Null)
3536let gen_rsa ~bits =
37 let e = Z.(if bits < 24 then ~$3 else ~$0x10001) in
···83 let msg =
84 let size = bits // 8 in
85 let buf = Bytes.create size in
86+ Crypto_rng.generate_into buf ~off:0 size;
87+ let i = 1 + Randomconv.int ~bound:(pred size) Crypto_rng.generate in
88 Bytes.set_uint8 buf 0 0;
89 Bytes.(set_uint8 buf i (get_uint8 buf i lor 2));
90 Bytes.unsafe_to_string buf
···103let pkcs_message_for_bits bits =
104 let padding = 12 in
105 let size = bits // 8 - padding in
106+ assert (size >= 0) ; Crypto_rng.generate size
107108let rsa_pkcs1_encode_selftest ~bits n =
109 "selftest" >:: times ~n @@ fun _ ->
···119 let open Digestif.SHA1 in
120 "selftest" >:: times ~n @@ fun _ ->
121 let key = gen_rsa ~bits:(Rsa.PKCS1.min_key `SHA1)
122+ and msg = Crypto_rng.generate 47 in
123 let pkey = Rsa.pub_of_priv key in
124 assert_bool "invert 1" Rsa.PKCS1.(
125 verify ~key:pkey ~hashp:any (`Message msg)
···146 let module OAEP_SHA384 = Rsa.OAEP (Digestif.SHA384) in
147 "selftest" >:: times ~n @@ fun _ ->
148 let key = gen_rsa ~bits in
149+ let msg = Crypto_rng.generate (bits // 8 - 2 * Digestif.MD5.digest_size - 2) in
150 let enc = OAEP_MD5.encrypt ~key:(Rsa.pub_of_priv key) msg in
151 (match OAEP_MD5.decrypt ~key enc with
152 | None -> assert_failure "unpad failure"
153 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
154+ let msg = Crypto_rng.generate (bits // 8 - 2 * Digestif.SHA1.digest_size - 2) in
155 let enc = OAEP_SHA1.encrypt ~key:(Rsa.pub_of_priv key) msg in
156 (match OAEP_SHA1.decrypt ~key enc with
157 | None -> assert_failure "unpad failure"
158 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
159+ let msg = Crypto_rng.generate (bits // 8 - 2 * Digestif.SHA224.digest_size - 2) in
160 let enc = OAEP_SHA224.encrypt ~key:(Rsa.pub_of_priv key) msg in
161 (match OAEP_SHA224.decrypt ~key enc with
162 | None -> assert_failure "unpad failure"
163 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
164+ let msg = Crypto_rng.generate (bits // 8 - 2 * Digestif.SHA256.digest_size - 2) in
165 let enc = OAEP_SHA256.encrypt ~key:(Rsa.pub_of_priv key) msg in
166 (match OAEP_SHA256.decrypt ~key enc with
167 | None -> assert_failure "unpad failure"
168 | Some dec -> assert_oct_equal msg dec ~msg:"recovery failure");
169+ let msg = Crypto_rng.generate (bits // 8 - 2 * Digestif.SHA384.digest_size - 2) in
170 let enc = OAEP_SHA384.encrypt ~key:(Rsa.pub_of_priv key) msg in
171 (match OAEP_SHA384.decrypt ~key enc with
172 | None -> assert_failure "unpad failure"
···176 let module Pss_sha1 = Rsa.PSS (Digestif.SHA1) in
177 "selftest" >:: times ~n @@ fun _ ->
178 let key = gen_rsa ~bits
179+ and msg = Crypto_rng.generate 1024 in
180 let pkey = Rsa.pub_of_priv key in
181 let dgst = Digestif.SHA1.(digest_string msg |> to_raw_string) in
182 let signature = Pss_sha1.sign ~key (`Digest dgst) in
+1-1
tests/test_symmetric_runner.ml
···5 (fun ppf -> List.iter @@ fun x ->
6 Format.fprintf ppf "%s " @@
7 match x with `XOR -> "XOR" | `AES -> "AES" | `GHASH -> "GHASH")
8- Mirage_crypto.accelerated
910let suite =
11 "All" >::: [
···5 (fun ppf -> List.iter @@ fun x ->
6 Format.fprintf ppf "%s " @@
7 match x with `XOR -> "XOR" | `AES -> "AES" | `GHASH -> "GHASH")
8+ Crypto.accelerated
910let suite =
11 "All" >::: [