tech-userlevel archive

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

Re: getrandom and getentropy



> Date: Sun, 3 May 2020 19:13:23 +0000
> From: nia <nia%NetBSD.org@localhost>
> 
> Since most of the objections so far have been aimed at the design
> and implementation of getrandom, does anyone have anything bad to say
> about getentropy?

That's what I had in mind at the start of the thread after verifying
_that_ most other systems implement something called getentropy, under
the assumption that they would all agree on the semantics.

But on closer inspection, it's not clear there's a consensus on what
the semantics is supposed to be -- apparently _what_ everyone seems to
implement is slightly different:

- OpenBSD originally defined getentropy to be block-never, as in
  getrandom(GRND_INSECURE)

- glibc, FreeBSD, and illumos implement block-at-boot, as in
  getrandom(0)

- Oracle Solaris maybe implements block-often, as in traditional
  /dev/random, but it's not clear; it might be block-at-boot (I don't
  have source code to reference, but there is some weak evidence that
  Oracle's getentropy is or was painfully slow, which might arise from
  blocking repeatedly, whereas getrandom worked fine:
  <https://bugs.python.org/issue25003>)

So I'm not longer confident that the name is meaningfully reliable as
an API to adopt, and if anything OpenBSD is in the minority now in
treating it as our sysctl kern.arandom semantics -- in spite of the
fact that OpenBSD introduced the name in the first place.

In contrast, the semantics of getrandom is clear once it is written
down more clearly than the Linux man page, even if the GRND_RANDOM
part of it is silly.  Specifically, it seems to be the case that:

- The following idiom will reliably either generate a 32-byte key or
  block until the system thinks it is seeded (or abort if anything is
  horribly awry), everywhere it is defined:

	if (getrandom(buf, 32, 0) == -1)
		abort();

- The following idiom (the non-blocking version of the above) will
  reliably either generate a 32-byte key or abort immediately if the
  system is _not_ seeded (or if anything is horribly awry), everywhere
  it is defined:

	if (getrandom(buf, 32, GRND_NONBLOCK) == -1)
		abort();

- The following idiom will reliably either generate 32 bytes of data
  derived from whatever is in the pool (or abort immediately if
  anything is horribly awry), without blocking, irrespective of
  whether the system is seeded, everywhere it is defined:

	if (getrandom(buf, 32, GRND_INSECURE) == -1)
		abort();

(This applies up to 256 bytes, actually; for longer requests,
behaviour seems to vary and you may need to check the return code for
truncation.  But 32 is more than you ever need for cryptography.)

These are all more or less reasonable things to want to express in an
application or library but none of these statements remains generally
true if I replace getrandom(buf,32,...) by getentropy(buf,32).


Home | Main Index | Thread Index | Old Index