• H
    random: account for entropy loss due to overwrites · 30e37ec5
    H. Peter Anvin 提交于
    When we write entropy into a non-empty pool, we currently don't
    account at all for the fact that we will probabilistically overwrite
    some of the entropy in that pool.  This means that unless the pool is
    fully empty, we are currently *guaranteed* to overestimate the amount
    of entropy in the pool!
    
    Assuming Shannon entropy with zero correlations we end up with an
    exponentally decaying value of new entropy added:
    
    	entropy <- entropy + (pool_size - entropy) *
    		(1 - exp(-add_entropy/pool_size))
    
    However, calculations involving fractional exponentials are not
    practical in the kernel, so apply a piecewise linearization:
    
    	  For add_entropy <= pool_size/2 then
    
    	  (1 - exp(-add_entropy/pool_size)) >= (add_entropy/pool_size)*0.7869...
    
    	  ... so we can approximate the exponential with
    	  3/4*add_entropy/pool_size and still be on the
    	  safe side by adding at most pool_size/2 at a time.
    
    In order for the loop not to take arbitrary amounts of time if a bad
    ioctl is received, terminate if we are within one bit of full.  This
    way the loop is guaranteed to terminate after no more than
    log2(poolsize) iterations, no matter what the input value is.  The
    vast majority of the time the loop will be executed exactly once.
    
    The piecewise linearization is very conservative, approaching 3/4 of
    the usable input value for small inputs, however, our entropy
    estimation is pretty weak at best, especially for small values; we
    have no handle on correlation; and the Shannon entropy measure (Rényi
    entropy of order 1) is not the correct one to use in the first place,
    but rather the correct entropy measure is the min-entropy, the Rényi
    entropy of infinite order.
    
    As such, this conservatism seems more than justified.
    
    This does introduce fractional bit values.  I have left it to have 3
    bits of fraction, so that with a pool of 2^12 bits the multiply in
    credit_entropy_bits() can still fit into an int, as 2*(3+12) < 31.  It
    is definitely possible to allow for more fractional accounting, but
    that multiply then would have to be turned into a 32*32 -> 64 multiply.
    Signed-off-by: NH. Peter Anvin <hpa@linux.intel.com>
    Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
    Cc: DJ Johnston <dj.johnston@intel.com>
    30e37ec5
random.c 47.5 KB