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

2014-07-21 Thread Dwayne Litzenberger

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 dl...@dlitz.net
OpenPGP: 19E1 1FE8 B3CF F273 ED17  4A24 928C EC13 39C2 5CF7


pgpApJX2wIboT.pgp
Description: PGP signature


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

2014-07-20 Thread Dwayne Litzenberger

On Thu, Jul 17, 2014 at 01:01:16PM -0400, Theodore Ts'o wrote:

The getrandom(2) system call is a superset of getentropy(2).  When we
add the support for this into glibc, it won't be terribly difficult
nor annoying to drop the following in alongside the standard support
needed for any new system call:

int getentropy(void *buf, size_t buflen)
{
int ret;

ret = getentropy(buf, buflen, 0);
return (ret  0) ? 0 : ret;
}

The reason for the additional flags is that I'm trying to solve more
problems than just getentropy()'s raison d'etre.  The discussion of
this is in the commit description; let me know if there bits that I
could make clearer.


This could still return predictable bytes during early boot, though, 
right?


--
Dwayne C. Litzenberger dl...@dlitz.net
OpenPGP: 19E1 1FE8 B3CF F273 ED17  4A24 928C EC13 39C2 5CF7
--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html