Re: [PATCH, RFC] random: introduce getrandom(2) system call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 17, 2014 at 05:18:15AM -0400, Theodore Ts'o wrote:
SYNOPSIS
	#include <linux/random.h>

	int getrandom(void *buf, size_t buflen, unsigned int flags);

DESCRIPTION

	The system call getrandom() fills the buffer pointed to by buf
	with up to buflen random bytes which can be used to seed user
	space random number generators (i.e., DRBG's) or for other
	cryptographic processes.  It should not be used Monte Carlo
	simulations or for other probabilistic sampling applications.

Aside from poor performance for the offending application, will anything
actually break if an application ignores this warning and makes heavy
use of getrandom(2)?  It would be helpful if the documentation made this
clearer, rather than just saying, "don't do that".

As the developer of a userspace crypto library, I can't always prevent
downstream developers from doing silly things, and many developers
simply don't understand different "kinds" of random numbers, so I prefer
to tell them to just use the kernel CSPRNG by default, and to ask for
help once they run into performance problems.  It's not ideal, but it's
safer than the alternative.[1]

	If the GRND_RANDOM flags bit is set, then draw from the
	/dev/random pool instead of /dev/urandom pool.  The /dev/random
	pool is limited based on the entropy that can be obtained from
	environmental noise, so if there is insufficient entropy, the
	requested number of bytes may not be returned.  If there is no
	entropy available at all, getrandom(2) will either return an
	error with errno set to EAGAIN, or block if the GRND_BLOCK flags
	bit is set.

	If the GRND_RANDOM flags bit is not set, then the /dev/raundom
	pool will be used.  Unlike reading from the /dev/urandom, if
	the urandom pool has not been sufficiently initialized,
	getrandom(2) will either return an error with errno set to
	EGAIN, or block if the GRND_BLOCK flags bit is set.

RETURN VALUE
      On success, the number of bytes that was returned is returned.

      On error, -1 is returned, and errno is set appropriately

Hm.  Is it correct that, in blocking mode, the call is guaranteed either
to return -EINVAL immediately, or to block until the buffer is
*completely* populated with buflen bytes?  If so, I think a few small
changes could make this a really nice interface to work with:

* Use blocking mode by default.

* Add a new flag called GRND_PARTIAL (replacing GRND_BLOCK), which
 indicates that the caller is prepared to handle a partial/incomplete
 result.

* On success with GRND_PARTIAL, return the number of bytes that were
 written into buf.  (Or -EAGAIN, as is currently done.)

* If GRND_PARTIAL is *not* set, just return 0 on success.  (This avoids
 all signed-unsigned confusion when buflen > INT_MAX.)

With those changes, it would be trivial for a userspace library to
implement a reliable RNG interface as recommended in [2] or [3]:

/*
* memzap(3)
*
* Fills the buffer pointed to by buf with exactly buflen random bytes
* suitable for cryptographic purposes.  Nothing is returned.
*
* This function is thread-safe, and is safe to call from inside a
* signal handler.
*
* It blocks if the kernel random number generator is not yet fully
* initialized (e.g. early in the boot process), and it may trigger
* abort(3) if invoked on an old kernel version that does not support
* the getrandom(2) system call.
*/
void memzap(void *buf, size_t buflen)
{
       int     ret;

       ret = getrandom(buf, buflen, 0);
       if (ret != 0) {
               perror("getrandom(2) failed");
               abort();
       }
}

Best,
- Dwayne

P.S.  If I had my way, I would also drop GRND_RANDOM.  Most software
won't use it, there's no legacy installed base, and no developer who
still wants that behavior can legitimately claim to care about RNG
availability guarantees, IMHO.  Anyone who really wants the old
/dev/random behavior can always just continue to use the existing
character device.  I don't really care enough to put up a fight about
it, though, as long as it doesn't affect the quality of the
non-GRND_RANDOM interface.


[1] On more than one occasion, I've seen developers use Python's
   standard "random" module to generate IVs.  I mean, why not?  IVs are
   public, right?
[2] http://cr.yp.to/highspeed/coolnacl-20120725.pdf
[3] https://groups.google.com/forum/#!msg/randomness-generation/4opmDHA6_3w/__TyKhbnNWsJ

--
Dwayne C. Litzenberger <dlitz@xxxxxxxxx>
OpenPGP: 19E1 1FE8 B3CF F273 ED17  4A24 928C EC13 39C2 5CF7

Attachment: pgp4Qk29xGg0S.pgp
Description: PGP signature


[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux