Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
mllib: Add a utility function for safely reading from /dev/urandom.
OCaml's buffered 'in_channel' has a 64k buffer, so using it to read a
few bytes from /dev/urandom removes a lot of the system's entropy (for
example /proc/sys/kernel/random/entropy_avail goes from ~3000 to 128).

This patch was originally by Edwin Török for builder.ml.  I
generalized it because there are two other places where we did
over-sized reads from /dev/urandom.
  • Loading branch information
rwmjones committed Nov 14, 2013
1 parent 544d6b2 commit f013b15
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 7 deletions.
1 change: 1 addition & 0 deletions builder/Makefile.am
Expand Up @@ -65,6 +65,7 @@ OBJECTS = \
$(top_builddir)/mllib/libdir.cmx \
$(top_builddir)/mllib/common_gettext.cmx \
$(top_builddir)/mllib/common_utils.cmx \
$(top_builddir)/mllib/urandom.cmx \
$(top_builddir)/mllib/random_seed.cmx \
$(top_builddir)/mllib/hostname.cmx \
$(top_builddir)/mllib/firstboot.cmx \
Expand Down
3 changes: 3 additions & 0 deletions mllib/Makefile.am
Expand Up @@ -48,6 +48,8 @@ SOURCES = \
tty-c.c \
tTY.mli \
tTY.ml \
urandom.mli \
urandom.ml \
uri-c.c \
uRI.mli \
uRI.ml
Expand All @@ -70,6 +72,7 @@ OBJECTS = \
libdir.cmx \
common_gettext.cmx \
common_utils.cmx \
urandom.cmx \
random_seed.cmx \
hostname.cmx \
firstboot.cmx \
Expand Down
9 changes: 2 additions & 7 deletions mllib/random_seed.ml
Expand Up @@ -78,13 +78,8 @@ and make_random_seed_file g file =
(* Default to 512 bytes of randomness. *)
512 in

let entropy =
(* Get n bytes of randomness from the host. *)
let chan = open_in "/dev/urandom" in
let buf = String.create n in
really_input chan buf 0 n;
close_in chan;
buf in
(* Get n bytes of randomness from the host. *)
let entropy = Urandom.urandom_bytes n in

if file_exists then (
(* Truncate the original file and append, in order to
Expand Down
48 changes: 48 additions & 0 deletions mllib/urandom.ml
@@ -0,0 +1,48 @@
(* Read /dev/urandom.
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)

(* Read and return N bytes (only) from /dev/urandom.
*
* As pointed out by Edwin Török, previous versions of this had a big
* problem. They used the OCaml buffered I/O library which would read
* a lot more data than requested. This version uses unbuffered I/O
* from the Unix module.
*)

open Unix

let open_urandom_fd () = openfile "/dev/urandom" [O_RDONLY] 0

let read_byte fd =
let s = String.make 1 ' ' in
fun () ->
if read fd s 0 1 = 0 then (
close fd;
raise End_of_file
);
Char.code s.[0]

let urandom_bytes n =
assert (n > 0);
let ret = String.make n ' ' in
let fd = open_urandom_fd () in
for i = 0 to n-1 do
ret.[i] <- Char.chr (read_byte fd ())
done;
close fd;
ret
22 changes: 22 additions & 0 deletions mllib/urandom.mli
@@ -0,0 +1,22 @@
(* Read /dev/urandom.
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)

(** Read and return N bytes (only) from /dev/urandom. *)

val urandom_bytes : int -> string
(** Read N bytes from /dev/urandom and return it as a binary string. *)
1 change: 1 addition & 0 deletions po/POTFILES-ml
Expand Up @@ -21,6 +21,7 @@ mllib/progress.ml
mllib/random_seed.ml
mllib/tTY.ml
mllib/uRI.ml
mllib/urandom.ml
resize/resize.ml
sparsify/sparsify.ml
sysprep/main.ml
Expand Down
1 change: 1 addition & 0 deletions sysprep/Makefile.am
Expand Up @@ -89,6 +89,7 @@ OBJECTS = \
$(top_builddir)/mllib/uRI.cmx \
$(top_builddir)/mllib/crypt-c.o \
$(top_builddir)/mllib/crypt.cmx \
$(top_builddir)/mllib/urandom.cmx \
$(top_builddir)/mllib/password.cmx \
$(top_builddir)/mllib/random_seed.cmx \
$(top_builddir)/mllib/hostname.cmx \
Expand Down

0 comments on commit f013b15

Please sign in to comment.