• Jason A. Donenfeld's avatar
    random: do not pretend to handle premature next security model · e85c0fc1
    Jason A. Donenfeld authored
    Per the thread linked below, "premature next" is not considered to be a
    realistic threat model, and leads to more serious security problems.
    
    "Premature next" is the scenario in which:
    
    - Attacker compromises the current state of a fully initialized RNG via
      some kind of infoleak.
    - New bits of entropy are added directly to the key used to generate the
      /dev/urandom stream, without any buffering or pooling.
    - Attacker then, somehow having read access to /dev/urandom, samples RNG
      output and brute forces the individual new bits that were added.
    - Result: the RNG never "recovers" from the initial compromise, a
      so-called violation of what academics term "post-compromise security".
    
    The usual solutions to this involve some form of delaying when entropy
    gets mixed into the crng. With Fortuna, this involves multiple input
    buckets. With what the Linux RNG was trying to do prior, this involves
    entropy estimation.
    
    However, by delaying when entropy gets mixed in, it also means that RNG
    compromises are extremely dangerous during the window of time before
    the RNG has gathered enough entropy, during which time nonces may become
    predictable (or repeated), ephemeral keys may not be secret, and so
    forth. Moreover, it's unclear how realistic "premature next" is from an
    attack perspective, if these attacks even make sense in practice.
    
    Put together -- and discussed in more detail in the thread below --
    these constitute grounds for just doing away with the current code that
    pretends to handle premature next. I say "pretends" because it wasn't
    doing an especially great job at it either; should we change our mind
    about this direction, we would probably implement Fortuna to "fix" the
    "problem", in which case, removing the pretend solution still makes
    sense.
    
    This also reduces the crng reseed period from 5 minutes down to 1
    minute. The rationale from the thread might lead us toward reducing that
    even further in the future (or even eliminating it), but that remains a
    topic of a future commit.
    
    At a high level, this patch changes semantics from:
    
        Before: Seed for the first time after 256 "bits" of estimated
        entropy have been accumulated since the system booted. Thereafter,
        reseed once every five minutes, but only if 256 new "bits" have been
        accumulated since the last reseeding.
    
        After: Seed for the first time after 256 "bits" of estimated entropy
        have been accumulated since the system booted. Thereafter, reseed
        once every minute.
    
    Most of this patch is renaming and removing: POOL_MIN_BITS becomes
    POOL_INIT_BITS, credit_entropy_bits() becomes credit_init_bits(),
    crng_reseed() loses its "force" parameter since it's now always true,
    the drain_entropy() function no longer has any use so it's removed,
    entropy estimation is skipped if we've already init'd, the various
    notifiers for "low on entropy" are now only active prior to init, and
    finally, some documentation comments are cleaned up here and there.
    
    Link: https://lore.kernel.org/lkml/YmlMGx6+uigkGiZ0@zx2c4.com/
    Cc: Theodore Ts'o <tytso@mit.edu>
    Cc: Nadia Heninger <nadiah@cs.ucsd.edu>
    Cc: Tom Ristenpart <ristenpart@cornell.edu>
    Reviewed-by: default avatarEric Biggers <ebiggers@google.com>
    Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
    e85c0fc1
random.c 49.6 KB