From a1933bd1847951b959016f59ee744d1b18a00142 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Fri, 14 Oct 2016 17:07:56 +0000
Subject: Clean up and modernize librandom.
Correct random number generation has historically been
suprisingly painful to achieve. There was no standard,
every system behaved in a subtly different way, and there
were a few userland initiatives to get decent randomness,
all incompatible of course.
The situation is a bit better now, we're heading towards
some standardization. The arc4random() series of functions
is a good API, and available on a lot of systems -
unfortunately not Linux, but on Linux the new getrandom()
makes using /dev/random obsolete.
So I removed the old crap in librandom, dropped EGD support,
dropped dynamic backend selection, made a single API series
(random_* instead of goodrandom_* and badrandom_*), added
an arc4random backend and a getrandom backend, and defaulted
to /dev/urandom backed up by SURF in the worst case. This
should be much smaller and logical. However, it's a major
API break, so the skarnet.org stack will be changed to
adapt.
---
configure | 33 +---------
doc/librandom/index.html | 89 ++++++++++++++++----------
package/deps.mak | 58 ++++-------------
src/include/skalibs/random.h | 29 +++------
src/include/skalibs/rrandom.h | 36 -----------
src/include/skalibs/surf.h | 6 +-
src/include/skalibs/unirandom.h | 56 ----------------
src/include/skalibs/unirandomdev.h | 19 ------
src/include/skalibs/unirandomegd.h | 17 -----
src/include/skalibs/unisurf.h | 16 -----
src/librandom/badrandom_char.c | 13 ----
src/librandom/badrandom_finish.c | 12 ----
src/librandom/badrandom_here.c | 40 ------------
src/librandom/badrandom_init.c | 10 ---
src/librandom/badrandom_int.c | 12 ----
src/librandom/badrandom_string.c | 12 ----
src/librandom/goodrandom_char.c | 13 ----
src/librandom/goodrandom_finish.c | 12 ----
src/librandom/goodrandom_here.c | 40 ------------
src/librandom/goodrandom_init.c | 10 ---
src/librandom/goodrandom_int.c | 12 ----
src/librandom/goodrandom_string.c | 12 ----
src/librandom/random-internal.h | 11 +---
src/librandom/random_char.c | 10 +++
src/librandom/random_finish.c | 45 +++++++++++++
src/librandom/random_init.c | 75 ++++++++++++++++++++++
src/librandom/random_makeseed.c | 44 +++++++++++++
src/librandom/random_mask2.c | 35 ----------
src/librandom/random_name.c | 9 ++-
src/librandom/random_sauniquename.c | 12 ++--
src/librandom/random_string.c | 66 +++++++++++++++++++
src/librandom/random_uint32.c | 56 ++++++++++++++++
src/librandom/random_unsort.c | 4 +-
src/librandom/randomegd_open.c | 20 ------
src/librandom/randomegd_readb.c | 27 --------
src/librandom/randomegd_readnb.c | 28 --------
src/librandom/rrandom_add.c | 13 ----
src/librandom/rrandom_finish.c | 14 ----
src/librandom/rrandom_name.c | 13 ----
src/librandom/rrandom_read.c | 21 ------
src/librandom/rrandom_readint.c | 25 --------
src/librandom/surf_autoinit.c | 10 ---
src/librandom/surf_here.c | 8 ---
src/librandom/surf_init.c | 11 ++--
src/librandom/surf_makeseed.c | 35 ----------
src/librandom/surf_sinit.c | 13 ----
src/librandom/unidevrandom.c | 38 -----------
src/librandom/unidevurandom.c | 38 -----------
src/librandom/unihasegd.c | 38 -----------
src/librandom/unirandom_finish.c | 12 ----
src/librandom/unirandom_init.c | 12 ----
src/librandom/unirandom_readb.c | 10 ---
src/librandom/unirandom_readnb.c | 10 ---
src/librandom/unirandom_register.c | 16 -----
src/librandom/unirandomdev.c | 51 ---------------
src/librandom/unirandomegd.c | 37 -----------
src/librandom/unisurf.c | 23 -------
src/librandom/unisurf_init.c | 18 ------
src/libstddjb/sauniquename.c | 6 +-
src/libunixonacid/atomic_rm_rf_tmp.c | 2 +-
src/libunixonacid/dd_commit.c | 4 +-
src/libunixonacid/dd_open_write.c | 2 +-
src/libunixonacid/mkdir_unique.c | 2 +-
src/libunixonacid/openwritenclose_devino_tmp.c | 2 +-
src/sysdeps/tryarc4random.c | 11 ++++
src/sysdeps/trydevrandom.c | 54 ----------------
src/sysdeps/trygetrandom.c | 22 +++++++
67 files changed, 434 insertions(+), 1136 deletions(-)
delete mode 100644 src/include/skalibs/rrandom.h
delete mode 100644 src/include/skalibs/unirandom.h
delete mode 100644 src/include/skalibs/unirandomdev.h
delete mode 100644 src/include/skalibs/unirandomegd.h
delete mode 100644 src/include/skalibs/unisurf.h
delete mode 100644 src/librandom/badrandom_char.c
delete mode 100644 src/librandom/badrandom_finish.c
delete mode 100644 src/librandom/badrandom_here.c
delete mode 100644 src/librandom/badrandom_init.c
delete mode 100644 src/librandom/badrandom_int.c
delete mode 100644 src/librandom/badrandom_string.c
delete mode 100644 src/librandom/goodrandom_char.c
delete mode 100644 src/librandom/goodrandom_finish.c
delete mode 100644 src/librandom/goodrandom_here.c
delete mode 100644 src/librandom/goodrandom_init.c
delete mode 100644 src/librandom/goodrandom_int.c
delete mode 100644 src/librandom/goodrandom_string.c
create mode 100644 src/librandom/random_char.c
create mode 100644 src/librandom/random_finish.c
create mode 100644 src/librandom/random_init.c
create mode 100644 src/librandom/random_makeseed.c
delete mode 100644 src/librandom/random_mask2.c
create mode 100644 src/librandom/random_string.c
create mode 100644 src/librandom/random_uint32.c
delete mode 100644 src/librandom/randomegd_open.c
delete mode 100644 src/librandom/randomegd_readb.c
delete mode 100644 src/librandom/randomegd_readnb.c
delete mode 100644 src/librandom/rrandom_add.c
delete mode 100644 src/librandom/rrandom_finish.c
delete mode 100644 src/librandom/rrandom_name.c
delete mode 100644 src/librandom/rrandom_read.c
delete mode 100644 src/librandom/rrandom_readint.c
delete mode 100644 src/librandom/surf_autoinit.c
delete mode 100644 src/librandom/surf_here.c
delete mode 100644 src/librandom/surf_makeseed.c
delete mode 100644 src/librandom/surf_sinit.c
delete mode 100644 src/librandom/unidevrandom.c
delete mode 100644 src/librandom/unidevurandom.c
delete mode 100644 src/librandom/unihasegd.c
delete mode 100644 src/librandom/unirandom_finish.c
delete mode 100644 src/librandom/unirandom_init.c
delete mode 100644 src/librandom/unirandom_readb.c
delete mode 100644 src/librandom/unirandom_readnb.c
delete mode 100644 src/librandom/unirandom_register.c
delete mode 100644 src/librandom/unirandomdev.c
delete mode 100644 src/librandom/unirandomegd.c
delete mode 100644 src/librandom/unisurf.c
delete mode 100644 src/librandom/unisurf_init.c
create mode 100644 src/sysdeps/tryarc4random.c
delete mode 100644 src/sysdeps/trydevrandom.c
create mode 100644 src/sysdeps/trygetrandom.c
diff --git a/configure b/configure
index 55136cc..122eb42 100755
--- a/configure
+++ b/configure
@@ -38,13 +38,11 @@ Optional features:
$package options:
--enable-libc-replacements use independent low-level primitives [disabled]
- --enable-egd=PATH support an EGD daemon listening on PATH as RNG [disabled]
--disable-ipv6 do not build IPv6 support [enabled]
--enable-iopause-select prefer select() over poll() for iopause implementation [disabled]
--enable-tai-clock assume the system clock is TAI-10 instead of UTC [disabled]
--enable-clock use clock_gettime() instead of gettimeofday() [disabled]
--enable-monotonic count time with CLOCK_MONOTONIC instead of CLOCK_REALTIME
- --enable-force-devr assume /dev/random exists and is valid [autodetection takes time]
--with-default-path=PATH default executable search path [/usr/bin:/usr/sbin:/bin:/sbin]
EOF
@@ -214,13 +212,11 @@ shared=true
static=true
slashpackage=false
replacements=false
-egd=
ipv6=true
select=false
taiclock=false
clockrt=false
clockmon=false
-forcedevr=false
ddefaultpath=/usr/bin:/usr/sbin:/bin:/sbin
defaultpath=$ddefaultpath
dpathorig=true
@@ -257,8 +253,6 @@ for arg ; do
--disable-slashpackage) sproot= ; slashpackage=false ;;
--enable-libc-replacements|--enable-libc-replacements=yes) replacements=true ;;
--disable-libc-replacements|--enable-libc-replacements=no) replacements=false ;;
- --enable-egd=*) egd=${arg#*=} ;;
- --disable-egd) egd= ;;
--enable-ipv6|--enable-ipv6=yes) ipv6=true ;;
--disable-ipv6|--enable-ipv6=no) ipv6=false ;;
--enable-iopause-select|--enable-iopause-select=yes) select=true ;;
@@ -269,8 +263,6 @@ for arg ; do
--disable-clock|--enable-clock=no) clockrt=false ;;
--enable-monotonic|--enable-monotonic=yes) clockmon=true ;;
--disable-monotonic|--enable-monotonic=no) clockmon=false ;;
- --enable-force-devr|--enable-force-devr=yes) forcedevr=true ;;
- --disable-force-devr|--enable-force-devr=no) forcedevr=false ;;
--with-default-path=*) defaultpath=${arg#*=} ; dpathorig=false ;;
--without-default-path) defaultpath=$ddefaultpath ; dpathorig=true ;;
--enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
@@ -403,10 +395,6 @@ if test -n "$sysdeps" ; then
sysclock_lib=$(cat $sysdeps/sysclock.lib)
tainnow_lib=$(cat $sysdeps/tainnow.lib)
util_lib=$(cat $sysdeps/util.lib)
- if test -n "$egd" ; then
- egd=$(grep -F egd: $sysdeps/sysdeps | cut -d' ' -f2-)
- echo "warning: --enable-egd option ignored, using sysdeps-provided value instead: $egd"
- fi
else
sysdeps=sysdeps.cfg
mkdir -p $sysdeps
@@ -500,21 +488,9 @@ EOF
choose c uint64t UINT64T 'uint64_t'
choose cl futimens FUTIMENS 'futimens()'
choose cl futimes FUTIMES 'futimes()'
+ choose cl arc4random ARC4RANDOM 'arc4random()'
+ choose cl getrandom GETRANDOM 'getrandom()'
- if $forcedevr ; then
- echo "/dev/random detection override required, assuming it exists and is working."
- echo "devrandom: yes" >> $sysdeps/sysdeps
- echo "#define ${package_macro_name}_HASDEVRANDOM" >> $sysdeps/sysdeps.h
- else
- choose clr devrandom DEVRANDOM /dev/random
- fi
- if test -n "$egd" ; then
- if echo "$egd" | grep -q '[^[:alnum:]/_-]' ; then
- fail "$0: invalid EGD path: $egd"
- fi
- echo "egd: $egd" >> $sysdeps/sysdeps
- echo "#define ${package_macro_name}_HASEGD \"$egd\"" >> $sysdeps/sysdeps.h
- fi
echo '#endif' >> $sysdeps/sysdeps.h
fi
@@ -626,11 +602,6 @@ if $select ; then
else
echo "#undef ${package_macro_name}_FLAG_PREFERSELECT"
fi
-if test -n "$egd" ; then
- echo "#define ${package_macro_name}_EGD $egd"
-else
- echo "#undef ${package_macro_name}_EGD"
-fi
echo
echo "#endif"
diff --git a/doc/librandom/index.html b/doc/librandom/index.html
index 8001811..183086a 100644
--- a/doc/librandom/index.html
+++ b/doc/librandom/index.html
@@ -51,64 +51,85 @@ If the EGD connection fails, a SURF PRNG is used.
function prototypes.
- High quality, cryptographically strong random data
+ Basic functions
unsigned char c ;
- unsigned int max ;
- unsigned int n ;
+ uint32_t max ;
+ uint32_t n ;
unsigned int b ;
char data[at least b] ;
int r ;
- goodrandom_init() ;
- c = goodrandom_char() ;
- n = goodrandom_int(max) ;
- r = goodrandom_string(data, b) ;
- goodrandom_finish() ;
+ r = random_init() ;
+ c = random_char() ;
+ n = random_uint32(max) ;
+ random_string(data, b) ;
+ random_finish() ;
- goodrandom_init() becomes optional with skalibs-0.43.
+ random_init() must be called before any other function in
+the random library. It returns 0 (and sets errno) on failure, and
+nonzero on success.
+
+
+
It is recommended that you let the library perform cleanups after you
-have used it, by calling goodrandom_finish().
+are done using it, by calling random_finish() - unless your
+process exits right away.
- - goodrandom_char() returns a random character
- - goodrandom_int(max) returns a random integer
-between 0 and max-1
- - goodrandom_string(data, b) puts
-b random bytes in data, which must be preallocated.
-It returns b if it succeeds, or a non-negative integer lesser
-than b if it fails for any reason.
+ - random_char() returns a random character.
+ - random_uint32(max) returns a random integer
+between 0 and max-1.
+ - random_string(data, b) fills
+b bytes in data (which must be preallocated)
+with random data.
+ Advanced functions
+
- If you have neither /dev/random nor EGD, a software PRNG is
-used. This PRNG is based on the
-SURF function, which
-is unpredictable enough for most uses.
+ void random_unsort (char *s, unsigned int n, unsigned int chunksize)
+Shuffles the array s (of size at least n*chunksize) by
+performing a random permutation of the n blocks of chunksize bytes.
+Bytes are not permuted inside chunks.
- Lower quality random data
-
- It works basically the same, by replacing goodrandom_* with
-badrandom_*. It uses /dev/urandom on systems that
-support it; on systems that do not, but support EGD, non-blocking calls
-to EGD are made ; if that is not enough, or EGD is not supported,
-the SURF generator is used.
+ void random_name (char *s, unsigned int n)
+Writes n random readable ASCII characters into s:
+letters, numbers, hyphens or underscores. Does not terminate with a
+null character.
- The point of badrandom is to get random bytes instantly,
-even at the expense of quality; whereas goodrandom always returns
-high-quality random bytes, but may block if entropy is insufficient. In
-practice, in spite of its name, badrandom will return quite
-unpredictable pseudo-random data, so goodrandom should be used
-only when paranoia is the rule and blocking is an option.
+ int random_sauniquename (stralloc *sa, unsigned int n)
+Appends a (non-null-terminated) unique, unpredictable ASCII name to the
+stralloc *sa. That
+name includes n randomly generated ASCII characters.
+ Notes
+
+
+ - The random library is a thin wrapper around the best
+available random generator provided by the underlying system. By
+decreasing order of preference, it will use the following
+implementations if available:
+
+ - The random_init() function tries to automatically add some
+reasonably random data to the underlying random generator's entropy pool.
+However, that pseudorandom data is not 100% unpredictable, so it will not
+replace proper seeding of the random generator at boot time.
+
+