mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 00:40:03 +00:00
![Daniel Borkmann](/assets/img/avatar_default.png)
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 */
|