forked from mirrors/linux
		
	This patch addresses a couple of minor items, mostly addesssing
prandom_bytes(): 1) prandom_bytes{,_state}() should use size_t
for length arguments, 2) We can use put_unaligned() when filling
the array instead of open coding it [ perhaps some archs will
further benefit from their own arch specific implementation when
GCC cannot make up for it ], 3) Fix a typo, 4) Better use unsigned
int as type for getting the arch seed, 5) Make use of
prandom_u32_max() for timer slack.
Regarding the change to put_unaligned(), callers of prandom_bytes()
which internally invoke prandom_bytes_state(), don't bother as
they expect the array to be filled randomly and don't have any
control of the internal state what-so-ever (that's also why we
have periodic reseeding there, etc), so they really don't care.
Now for the direct callers of prandom_bytes_state(), which
are solely located in test cases for MTD devices, that is,
drivers/mtd/tests/{oobtest.c,pagetest.c,subpagetest.c}:
These tests basically fill a test write-vector through
prandom_bytes_state() with an a-priori defined seed each time
and write that to a MTD device. Later on, they set up a read-vector
and read back that blocks from the device. So in the verification
phase, the write-vector is being re-setup [ so same seed and
prandom_bytes_state() called ], and then memcmp()'ed against the
read-vector to check if the data is the same.
Akinobu, Lothar and I also tested this patch and it runs through
the 3 relevant MTD test cases w/o any errors on the nandsim device
(simulator for MTD devs) for x86_64, ppc64, ARM (i.MX28, i.MX53
and i.MX6):
  # modprobe nandsim first_id_byte=0x20 second_id_byte=0xac \
                     third_id_byte=0x00 fourth_id_byte=0x15
  # modprobe mtd_oobtest dev=0
  # modprobe mtd_pagetest dev=0
  # modprobe mtd_subpagetest dev=0
We also don't have any users depending directly on a particular
result of the PRNG (except the PRNG self-test itself), and that's
just fine as it e.g. allowed us easily to do things like upgrading
from taus88 to taus113.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Tested-by: Akinobu Mita <akinobu.mita@gmail.com>
Tested-by: Lothar Waßmann <LW@KARO-electronics.de>
Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
		
	
			
		
			
				
	
	
		
			115 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			115 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * include/linux/random.h
 | 
						|
 *
 | 
						|
 * Include file for the random number generator.
 | 
						|
 */
 | 
						|
#ifndef _LINUX_RANDOM_H
 | 
						|
#define _LINUX_RANDOM_H
 | 
						|
 | 
						|
#include <uapi/linux/random.h>
 | 
						|
 | 
						|
extern void add_device_randomness(const void *, unsigned int);
 | 
						|
extern void add_input_randomness(unsigned int type, unsigned int code,
 | 
						|
				 unsigned int value);
 | 
						|
extern void add_interrupt_randomness(int irq, int irq_flags);
 | 
						|
 | 
						|
extern void get_random_bytes(void *buf, int nbytes);
 | 
						|
extern void get_random_bytes_arch(void *buf, int nbytes);
 | 
						|
void generate_random_uuid(unsigned char uuid_out[16]);
 | 
						|
extern int random_int_secret_init(void);
 | 
						|
 | 
						|
#ifndef MODULE
 | 
						|
extern const struct file_operations random_fops, urandom_fops;
 | 
						|
#endif
 | 
						|
 | 
						|
unsigned int get_random_int(void);
 | 
						|
unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 | 
						|
 | 
						|
u32 prandom_u32(void);
 | 
						|
void prandom_bytes(void *buf, size_t nbytes);
 | 
						|
void prandom_seed(u32 seed);
 | 
						|
void prandom_reseed_late(void);
 | 
						|
 | 
						|
struct rnd_state {
 | 
						|
	__u32 s1, s2, s3, s4;
 | 
						|
};
 | 
						|
 | 
						|
u32 prandom_u32_state(struct rnd_state *state);
 | 
						|
void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
 | 
						|
 | 
						|
/**
 | 
						|
 * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro)
 | 
						|
 * @ep_ro: right open interval endpoint
 | 
						|
 *
 | 
						|
 * Returns a pseudo-random number that is in interval [0, ep_ro). Note
 | 
						|
 * that the result depends on PRNG being well distributed in [0, ~0U]
 | 
						|
 * u32 space. Here we use maximally equidistributed combined Tausworthe
 | 
						|
 * generator, that is, prandom_u32(). This is useful when requesting a
 | 
						|
 * random index of an array containing ep_ro elements, for example.
 | 
						|
 *
 | 
						|
 * Returns: pseudo-random number in interval [0, ep_ro)
 | 
						|
 */
 | 
						|
static inline u32 prandom_u32_max(u32 ep_ro)
 | 
						|
{
 | 
						|
	return (u32)(((u64) prandom_u32() * ep_ro) >> 32);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Handle minimum values for seeds
 | 
						|
 */
 | 
						|
static inline u32 __seed(u32 x, u32 m)
 | 
						|
{
 | 
						|
	return (x < m) ? x + m : x;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * prandom_seed_state - set seed for prandom_u32_state().
 | 
						|
 * @state: pointer to state structure to receive the seed.
 | 
						|
 * @seed: arbitrary 64-bit value to use as a seed.
 | 
						|
 */
 | 
						|
static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
 | 
						|
{
 | 
						|
	u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
 | 
						|
 | 
						|
	state->s1 = __seed(i,   2U);
 | 
						|
	state->s2 = __seed(i,   8U);
 | 
						|
	state->s3 = __seed(i,  16U);
 | 
						|
	state->s4 = __seed(i, 128U);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef CONFIG_ARCH_RANDOM
 | 
						|
# include <asm/archrandom.h>
 | 
						|
#else
 | 
						|
static inline int arch_get_random_long(unsigned long *v)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
static inline int arch_get_random_int(unsigned int *v)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
static inline int arch_has_random(void)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
static inline int arch_get_random_seed_long(unsigned long *v)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
static inline int arch_get_random_seed_int(unsigned int *v)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
static inline int arch_has_random_seed(void)
 | 
						|
{
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* Pseudo random number generator from numerical recipes. */
 | 
						|
static inline u32 next_pseudo_random32(u32 seed)
 | 
						|
{
 | 
						|
	return seed * 1664525 + 1013904223;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* _LINUX_RANDOM_H */
 |