All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: random(4) changes
@ 2016-04-26  1:59 George Spelvin
  2016-04-26 18:43 ` Stephan Mueller
  0 siblings, 1 reply; 40+ messages in thread
From: George Spelvin @ 2016-04-26  1:59 UTC (permalink / raw)
  To: sandyinchina; +Cc: herbert, linux, linux-crypto, linux-kernel, smueller, tytso

I just discovered this huge conversation and am trying to read it all
and get caught up.

I know I should finish reading before I start writing, but too many ideas
are bubbling up.


> not the rest of Stephan's input handling code: the parity
> calculation and XORing the resulting single bit into the entropy pool.

Indeed, this is an incredibly popular novice mistake and I don't
understand why people keep making it.

Look, *we don't know how* much entropy is in any given sample.  It's
unmeasurable in practice, so /dev/random uses some heuristics and
a huge amount of conservatism.

Because of the crude nature of this estimate, the amount of entropy
that's *probably* there is much larger than the computed guarantee.

To preserve this "bonus entropy", it's very important *not* to
have any bottlenecks like hashing down to a single bit.

Real events consist of a lot of highly predictable low-entropy samples,
with an occasional high-entropy exception.  Even if the average is less
than one bit, you want to ensure there's plenty of room for much *more*
than one bit so you aren't throwing away occasional high-entropy data.

This is why the current per-CPU fast pools are 128 bits and spilled *long*
before they approach full.

Precisely because the entropy estimate is so poor, I'd like *at least*
8 times as many bits as the entropy estimate, and more isn't a bad thing.

Eventually, you have to narrow it down to N strongly random bits with N
bits of entropy, but when you do that:

1. Use the largest batches possible, averaging over as much input as
   possible, and
2. Use a good collision-resistant, and preferably cryptographically
   strong, hash.  /dev/random's CRC-based input mix is pretty much
   the lightest defensible thing.  XOR is bad for for the same reason
   that any additive checksum is weak.


> I also quite like Stephan's idea of replacing the two output pools
> with a NIST-approved DBRG, mainly because this would probably make
> getting various certifications easier.

Do you know of an example of such a certification?

I don't really *mind* the NIST DRBGs (well, except for Dual_EC_DRBG
of course), but they don't really *help* in this context, either.

The good and bad thing about them is that they're highly correlated to
the strength of the underlying primitives.  If you're already relying
on AES in your application, then an AES-based DRBG avoids adding another
algorithm to your attack surface.  (Be it cryptanalytic, implementation,
or side channel.)

They also provide a nice reliable cookbook solution to anti-backtracking
and incorporating weakly random seed material (the timestamps) into
their state.

If they're not seeded with full entropy, then an algorithm like CTR_DRBG
isn't significantly *stronger* the underlying cipher.  Which is not
wonderful if /dev/random uses AES and someone's generating a Keccak key
with it (or vice versa).

And if they are seeded with full entropy, they aren't contrbuting
anything; it's just waving a dead chicken over your already-secure
input seed.

If waving a dead chicken would help with some real-world bureaucratic
obstacle, I don't mind, but otherwise it's pointless bloat.

(Exception: for large amounts of output, NIST's DRBGs have the problem
that they are bottlenecked at "seedlen" bits of internal state.
This makes sense for their intended use, which is in an application
with a specific security requirement, but an issue for a fully
general-purpose random bit source.)


> In the current driver -- and I think in Stephan's, though I have not
> looked at his code in any detail, only his paper -- heavy use of
> /dev/urandom or the kernel get_random_bytes() call can deplete the
> entropy available to /dev/random. That can be a serious problem in
> some circumstances, but I think I have a fix.

Actually, that hasn't been too big a problem for a while.  Of course
it depletes it *somewhat*, and it should, but there's the contents of
B plus some reserved in I (see rsvd_bytes in xfer_secondary_pool())
that won't be used up.

> You have an input pool (I) plus a blocking pool (B) & a non-blocking
> pool (NB). The problem is what to do when NB must produce a lot of
> output but you do not want to deplete I too much. B & NB might be
> replaced by DBRGs and the problem would not change.

I, B and NB *are* DRBGs, just not the NIST design.

> B must be reseeded before every /dev/random output, NB after some
> number of output blocks. I used #define SAFE_OUT 503 but some other
> number might be better depending how NB is implemented & how
> paranoid/conservative one feels.

Actually, it's better to use Ferguson & Schneier's idea of "catastropic
reseeding".  If you never want to block, you can never guarantee
reseeding.  This is not a big problem; a decent DRBG can generate
petabytes of output without reseeding.

(The reseed interval should be no more than the square root of the
state size, to force a reseed before a cycle appears.  NIST further
clamp it to 2^48, but that's somewhat arbitrary.)

What's more important is to reseed *enough* to "lose the tail"
if someone has captured the state.  If you reseed 1 bit after
each operation, then someone making frequent requests can
easily solve for the unknown seed bits.  If you wait and
reseed 256 bits all at once, they are locked out.

> B can only produce one full-entropy output, suitable for /dev/random,
> per reseed but B and NB are basically the same design so B can also
> produce SAFE_OUT reasonably good random numbers per reseed.

No, it can't.  I'll explain why this specifically doesn't work,
and then discuss the general problem.


The B pool keeps internal state.  Although it aims to provide
inforamtion-theoretic secure output, the antibacktracking is only
computationally secure; the generate function applies a one-way function
to the state so it's infeasible to compute the previous state (and thus
the previous output), but if someone captures the kernel state *and*
has a radical cryptanalytic advance, it's theoretically possible to
gain knowledge about previous outputs.

(The reason for this is that information-theoretic secure
antibacktracking is hugely wasteful of entropy.)

But if you *ever* use the B pool to generate more output than
it has seed entropy in, you are revealing enough information to
(assuming infinite computational power) compute the previous
state, or at least learn something about the previous state,
and this the previous output.

The security guarantee of /dev/random requires that B is never
used to generate more output than its seed entropy.

(This was the problem with the original one-pool Linux /dev/random,
which is why the current three-pool design was developed.  If you want
to ditch it, we can go back to the much simpler one-pool design.)

> Use those
> to reseed NB.and you reduce the load on I for reseeding NB from
> SAFE_OUT (use I every time NB is reseeded) to SAFE_OUT*SAFE_OUT (use I
> only to reseed B).

Your idea is based on a solid one: if you double the number of internal
state bits, you square the necessary reseed interval.  But there's
no advantage to doing it this particular way.  And the current
1024-bit output pools have such a long period it's a non-issue.


The more general issue is a problem with what I call "bonus entropy"
in the random pools.  As described above, if you ever remove from
a pool more bits than you are sure there is entropy, you can recover
some information about *previous* output bits.  It's computationally
infeasible to recover, but not information-theoretically secure,
which is what the blocking device aims for.

This means that not only may we not pull more bits from B than
we have guaranteed seed entropy, we may not pull the bits from I
either!

I really wish we could feed this "bonus entropy" into NB somehow, but
AFAICT it's impossible.

The only benefit we get from the bonus entropy is that it stays in I
and helps protect it from any later entropy underestimates.

If anyone can figure out a way to get more use out of it than currently,
that would be a significant advance.

^ permalink raw reply	[flat|nested] 40+ messages in thread
* random(4) changes
@ 2016-04-22 22:27 Sandy Harris
  2016-04-23  7:52 ` Stephan Mueller
                   ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Sandy Harris @ 2016-04-22 22:27 UTC (permalink / raw)
  To: LKML, linux-crypto
  Cc: Theodore Ts'o, Jason Cooper, John Denker, H. Peter Anvin,
	Stephan Mueller

Stephan has recently proposed some extensive changes to this driver,
and I proposed a quite different set earlier. My set can be found at:
https://github.com/sandy-harris

This post tries to find the bits of both proposals that seem clearly
worth doing and entail neither large implementation problems nor large
risk of throwing out any babies with the bathwater.

Unfortunately, nothing here deals with the elephant in the room -- the
distinctly hard problem of making sure the driver is initialised well
enough & early enough. That needs a separate post, probably a separate
thread. I do not find Stepan's solution to this problem plausible and
my stuff does not claim to deal with it, though it includes some
things that might help.

I really like Stephan's idea of simplifying the interrupt handling,
replacing the multiple entropy-gathering calls in the current driver
with one routine called for all interrupts. See section 1.2 of his
doc. That seems to me a much cleaner design, easier both to analyse
and to optimise as a fast interrupt handler. I also find Stephan's
arguments that this will work better on modern  systems -- VMs,
machines with SSDs, etc. -- quite plausible.

Note, though, that I am only talking about the actual interrupt
handling, not the rest of Stephan's input handling code: the parity
calculation and XORing the resulting single bit into the entropy pool.
I'd be happier, at least initially, with a patch that only implemented
a single-source interrupt handler that gave 32 or 64 bits to existing
input-handling code.

Stephan: would you want to provide such a patch?
Ted: would you be inclined to accept it?

I also quite like Stephan's idea of replacing the two output pools
with a NIST-approved DBRG, mainly because this would probably make
getting various certifications easier. I also like the idea of using
crypto lib code for that since it makes both testing & maintenance
easier. This strikes me, though, as a do-when-convenient sort of
cleanup task, not at all urgent unless there are specific
certifications we need soon.

As for my proposals, I of course think they are full of good ideas,
but there's only one I think is really important.

In the current driver -- and I think in Stephan's, though I have not
looked at his code in any detail, only his paper -- heavy use of
/dev/urandom or the kernel get_random_bytes() call can deplete the
entropy available to /dev/random. That can be a serious problem in
some circumstances, but I think I have a fix.

You have an input pool (I) plus a blocking pool (B) & a non-blocking
pool (NB). The problem is what to do when NB must produce a lot of
output but you do not want to deplete I too much. B & NB might be
replaced by DBRGs and the problem would not change.

B must be reseeded before very /dev/random output, NB after some
number of output blocks. I used #define SAFE_OUT 503 but some other
number might be better depending how NB is implemented & how
paranoid/conservative one feels.

B can only produce one full-entropy output, suitable for /dev/random,
per reseed but B and NB are basically the same design so B can also
produce SAFE_OUT reasonably good random numbers per reseed. Use those
to reseed NB.and you reduce the load on I for reseeding NB from
SAFE_OUT (use I every time NB is reseeded) to SAFE_OUT*SAFE_OUT (use I
only to reseed B).

This does need analysis by cryptographers, but at a minimum it is
basically plausible and, even with some fairly small value for
SAFE_OUT, it greatly alleviates the problem.

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2016-04-29 22:32 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-26  1:59 random(4) changes George Spelvin
2016-04-26 18:43 ` Stephan Mueller
2016-04-26 20:43   ` George Spelvin
2016-04-26 21:01     ` Stephan Mueller
2016-04-27  0:23       ` George Spelvin
2016-04-27 18:03         ` George Spelvin
2016-04-28 20:15         ` Stephan Mueller
2016-04-29  7:29           ` George Spelvin
2016-04-29  8:02             ` Stephan Mueller
2016-04-29  9:34               ` George Spelvin
2016-04-29  9:53                 ` Stephan Mueller
2016-04-29 11:04                   ` George Spelvin
2016-04-29 11:18                     ` Stephan Mueller
2016-04-29 18:02                       ` George Spelvin
2016-04-29 18:41                         ` Stephan Mueller
2016-04-29 20:08                           ` George Spelvin
2016-04-29 21:54                             ` Stephan Mueller
2016-04-29 22:32                               ` George Spelvin
2016-04-29  0:47         ` George Spelvin
  -- strict thread matches above, loose matches on Subject: below --
2016-04-22 22:27 Sandy Harris
2016-04-23  7:52 ` Stephan Mueller
2016-04-24  2:03 ` Theodore Ts'o
2016-04-24  8:03   ` Stephan Mueller
2016-04-26  3:07     ` Theodore Ts'o
2016-04-26 11:04       ` Herbert Xu
2016-04-26 20:47         ` Andi Kleen
2016-04-27  4:23           ` Herbert Xu
2016-04-26 18:24       ` Stephan Mueller
2016-04-26 18:44       ` Pavel Machek
2016-04-26 18:55         ` Stephan Mueller
2016-04-26 19:41           ` Pavel Machek
2016-04-25 16:06 ` Andi Kleen
2016-04-25 17:25   ` Stephan Mueller
2016-04-25 17:38     ` Andi Kleen
2016-04-25 17:56       ` Stephan Mueller
2016-04-25 19:35         ` Andi Kleen
2016-04-26 12:01           ` Stephan Mueller
2016-04-27 17:47           ` Stephan Mueller
2016-04-26  1:00   ` Theodore Ts'o
2016-04-26 12:42   ` Sandy Harris

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.