Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle CPU_RNG failures in OCaml: #255

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rng/async/mirage_crypto_rng_async.ml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ let periodically_collect_getrandom_entropy time_source span =
let idx = ref 0 in
let f () =
incr idx;
String.sub random ~pos:(per_pool * (pred !idx)) ~len:per_pool
Ok (String.sub random ~pos:(per_pool * (pred !idx)) ~len:per_pool)
in
Entropy.feed_pools None source f)

Expand Down
2 changes: 1 addition & 1 deletion rng/eio/mirage_crypto_rng_eio.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let periodically_feed_entropy env delta source =
let idx = ref 0 in
let f () =
incr idx;
String.sub random (per_pool * (pred !idx)) per_pool
Ok (String.sub random (per_pool * (pred !idx)) per_pool)
in
Entropy.feed_pools None source f
in
Expand Down
21 changes: 13 additions & 8 deletions rng/entropy.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
module Cpu_native = struct

external cycles : unit -> int = "mc_cycle_counter" [@@noalloc]
external rdseed : unit -> int = "mc_cpu_rdseed" [@@noalloc]
external rdrand : unit -> int = "mc_cpu_rdrand" [@@noalloc]
external rdseed : bytes -> int -> bool = "mc_cpu_rdseed" [@@noalloc]
external rdrand : bytes -> int -> bool = "mc_cpu_rdrand" [@@noalloc]
external rng_type : unit -> int = "mc_cpu_rng_type" [@@noalloc]

let cpu_rng =
Expand Down Expand Up @@ -119,10 +119,9 @@ let cpu_rng_bootstrap =
| None -> Error `Not_supported
| Some insn ->
let cpu_rng_bootstrap id =
let r = cpu_rng insn () in
if r = 0 then failwith "Mirage_crypto_rng.Entropy: 0 is a bad CPU RNG value";
let buf = Bytes.create 10 in
Bytes.set_int64_le buf 2 (Int64.of_int r);
let r = cpu_rng insn buf 2 in
if not r then failwith "Mirage_crypto_rng.Entropy: CPU RNG broken";
write_header id buf;
Bytes.unsafe_to_string buf
in
Expand Down Expand Up @@ -150,7 +149,11 @@ let feed_pools g source f =
let g = match g with None -> Some (Rng.default_generator ()) | Some g -> Some g in
let `Acc handle = Rng.accumulate g source in
for _i = 0 to pred (Rng.pools g) do
handle (f ())
match f () with
| Ok data -> handle data
| Error `No_random_available ->
(* should we log a message? *)
()
done

let cpu_rng =
Expand All @@ -165,8 +168,10 @@ let cpu_rng =
in
let f () =
let buf = Bytes.create 8 in
Bytes.set_int64_le buf 0 (Int64.of_int (randomf ()));
Bytes.unsafe_to_string buf
if randomf buf 0 then
Ok (Bytes.unsafe_to_string buf)
else
Error `No_random_available
in
fun () -> feed_pools g source f
in
Expand Down
2 changes: 1 addition & 1 deletion rng/lwt/mirage_crypto_rng_lwt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let getrandom_task delta source =
let idx = ref 0 in
let f () =
incr idx;
String.sub random (per_pool * (pred !idx)) per_pool
Ok (String.sub random (per_pool * (pred !idx)) per_pool)
in
Entropy.feed_pools None source f
in
Expand Down
5 changes: 4 additions & 1 deletion rng/miou/mirage_crypto_rng_miou_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ let getrandom delta source =
let size = per_pool * pools None in
let random = Mirage_crypto_rng_unix.getrandom size in
let idx = ref 0 in
let fn () = incr idx; String.sub random (per_pool * (pred !idx)) per_pool in
let fn () =
incr idx;
Ok (String.sub random (per_pool * (pred !idx)) per_pool)
in
Entropy.feed_pools None source fn in
periodic fn delta

Expand Down
4 changes: 2 additions & 2 deletions rng/mirage_crypto_rng.mli
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@ module Entropy : sig

(** {1 Periodic pulled sources} *)

val feed_pools : g option -> source -> (unit -> string) -> unit
val feed_pools : g option -> source -> (unit -> (string, [ `No_random_available ]) result) -> unit
(** [feed_pools g source f] feeds all pools of [g] using [source] by executing
[f] for each pool. *)

val cpu_rng : (g option -> unit -> unit, [`Not_supported]) Result.t
(** [cpu_rng g] uses the CPU RNG (rdrand or rdseed) to feed all pools
of [g]. It uses {!feed_pools} internally. If neither rdrand nor rdseed
are available, [fun () -> ()] is returned. *)
are available, [`Not_supported] is returned. *)

(**/**)
val id : source -> int
Expand Down
30 changes: 24 additions & 6 deletions src/native/entropy_cpu_stubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,27 @@
#define random_t unsigned long long
#define _rdseed_step _rdseed64_step
#define _rdrand_step _rdrand64_step
#define fill_bytes(buf, off, data) { \
(_bp_uint8_off(buf, off))[0] = (uint8_t)((data) >> 56); \
(_bp_uint8_off(buf, off))[1] = (uint8_t)((data) >> 48); \
(_bp_uint8_off(buf, off))[2] = (uint8_t)((data) >> 40); \
(_bp_uint8_off(buf, off))[3] = (uint8_t)((data) >> 32); \
(_bp_uint8_off(buf, off))[4] = (uint8_t)((data) >> 24); \
(_bp_uint8_off(buf, off))[5] = (uint8_t)((data) >> 16); \
(_bp_uint8_off(buf, off))[6] = (uint8_t)((data) >> 8); \
(_bp_uint8_off(buf, off))[7] = (uint8_t)((data)); \
}

#elif defined (__i386__)
#define random_t unsigned int
#define _rdseed_step _rdseed32_step
#define _rdrand_step _rdrand32_step
#define fill_bytes(buf, off, data) { \
(_bp_uint8_off(buf, off))[0] = (uint8_t)((data) >> 24); \
(_bp_uint8_off(buf, off))[1] = (uint8_t)((data) >> 16); \
(_bp_uint8_off(buf, off))[2] = (uint8_t)((data) >> 8); \
(_bp_uint8_off(buf, off))[3] = (uint8_t)((data)); \
}

#endif
#endif /* __i386__ || __x86_64__ */
Expand Down Expand Up @@ -229,29 +245,31 @@ static void detect (void) {
#endif
}

CAMLprim value mc_cpu_rdseed (value __unused(unit)) {
CAMLprim value mc_cpu_rdseed (value buf, value off) {
#ifdef __mc_ENTROPY__
random_t r = 0;
int ok = 0;
int i = RETRIES;
do { ok = _rdseed_step (&r); _mm_pause (); } while ( !(ok | !--i) );
return Val_long(r);
fill_bytes(buf, off, r);
hannesm marked this conversation as resolved.
Show resolved Hide resolved
return Val_bool (ok);
#else
/* ARM: CPU-assisted randomness here. */
return Val_long (0);
return Val_bool (0);
#endif
}

CAMLprim value mc_cpu_rdrand (value __unused(unit)) {
CAMLprim value mc_cpu_rdrand (value buf, value off) {
#ifdef __mc_ENTROPY__
random_t r = 0;
int ok = 0;
int i = RETRIES;
do { ok = _rdrand_step (&r); } while ( !(ok | !--i) );
return Val_long(r);
fill_bytes(buf, off, r);
return Val_bool (ok);
#else
/* ARM: CPU-assisted randomness here. */
return Val_long (0);
return Val_bool (0);
#endif
}

Expand Down
Loading