1 /* SPDX-License-Identifier: GPL-2.0 */ 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 2 /* 3 * include/linux/prandom.h 3 * include/linux/prandom.h 4 * 4 * 5 * Include file for the fast pseudo-random 32- 5 * Include file for the fast pseudo-random 32-bit 6 * generation. 6 * generation. 7 */ 7 */ 8 #ifndef _LINUX_PRANDOM_H 8 #ifndef _LINUX_PRANDOM_H 9 #define _LINUX_PRANDOM_H 9 #define _LINUX_PRANDOM_H 10 10 11 #include <linux/types.h> 11 #include <linux/types.h> 12 #include <linux/once.h> !! 12 #include <linux/percpu.h> 13 #include <linux/random.h> !! 13 >> 14 u32 prandom_u32(void); >> 15 void prandom_bytes(void *buf, size_t nbytes); >> 16 void prandom_seed(u32 seed); >> 17 void prandom_reseed_late(void); >> 18 >> 19 DECLARE_PER_CPU(unsigned long, net_rand_noise); >> 20 >> 21 #define PRANDOM_ADD_NOISE(a, b, c, d) \ >> 22 prandom_u32_add_noise((unsigned long)(a), (unsigned long)(b), \ >> 23 (unsigned long)(c), (unsigned long)(d)) >> 24 >> 25 #if BITS_PER_LONG == 64 >> 26 /* >> 27 * The core SipHash round function. Each line can be executed in >> 28 * parallel given enough CPU resources. >> 29 */ >> 30 #define PRND_SIPROUND(v0, v1, v2, v3) ( \ >> 31 v0 += v1, v1 = rol64(v1, 13), v2 += v3, v3 = rol64(v3, 16), \ >> 32 v1 ^= v0, v0 = rol64(v0, 32), v3 ^= v2, \ >> 33 v0 += v3, v3 = rol64(v3, 21), v2 += v1, v1 = rol64(v1, 17), \ >> 34 v3 ^= v0, v1 ^= v2, v2 = rol64(v2, 32) \ >> 35 ) >> 36 >> 37 #define PRND_K0 (0x736f6d6570736575 ^ 0x6c7967656e657261) >> 38 #define PRND_K1 (0x646f72616e646f6d ^ 0x7465646279746573) >> 39 >> 40 #elif BITS_PER_LONG == 32 >> 41 /* >> 42 * On 32-bit machines, we use HSipHash, a reduced-width version of SipHash. >> 43 * This is weaker, but 32-bit machines are not used for high-traffic >> 44 * applications, so there is less output for an attacker to analyze. >> 45 */ >> 46 #define PRND_SIPROUND(v0, v1, v2, v3) ( \ >> 47 v0 += v1, v1 = rol32(v1, 5), v2 += v3, v3 = rol32(v3, 8), \ >> 48 v1 ^= v0, v0 = rol32(v0, 16), v3 ^= v2, \ >> 49 v0 += v3, v3 = rol32(v3, 7), v2 += v1, v1 = rol32(v1, 13), \ >> 50 v3 ^= v0, v1 ^= v2, v2 = rol32(v2, 16) \ >> 51 ) >> 52 #define PRND_K0 0x6c796765 >> 53 #define PRND_K1 0x74656462 >> 54 >> 55 #else >> 56 #error Unsupported BITS_PER_LONG >> 57 #endif >> 58 >> 59 static inline void prandom_u32_add_noise(unsigned long a, unsigned long b, >> 60 unsigned long c, unsigned long d) >> 61 { >> 62 /* >> 63 * This is not used cryptographically; it's just >> 64 * a convenient 4-word hash function. (3 xor, 2 add, 2 rol) >> 65 */ >> 66 a ^= raw_cpu_read(net_rand_noise); >> 67 PRND_SIPROUND(a, b, c, d); >> 68 raw_cpu_write(net_rand_noise, d); >> 69 } 14 70 15 struct rnd_state { 71 struct rnd_state { 16 __u32 s1, s2, s3, s4; 72 __u32 s1, s2, s3, s4; 17 }; 73 }; 18 74 19 u32 prandom_u32_state(struct rnd_state *state) 75 u32 prandom_u32_state(struct rnd_state *state); 20 void prandom_bytes_state(struct rnd_state *sta 76 void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); 21 void prandom_seed_full_state(struct rnd_state 77 void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); 22 78 23 #define prandom_init_once(pcpu_state) 79 #define prandom_init_once(pcpu_state) \ 24 DO_ONCE(prandom_seed_full_state, (pcpu 80 DO_ONCE(prandom_seed_full_state, (pcpu_state)) 25 81 >> 82 /** >> 83 * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro) >> 84 * @ep_ro: right open interval endpoint >> 85 * >> 86 * Returns a pseudo-random number that is in interval [0, ep_ro). Note >> 87 * that the result depends on PRNG being well distributed in [0, ~0U] >> 88 * u32 space. Here we use maximally equidistributed combined Tausworthe >> 89 * generator, that is, prandom_u32(). This is useful when requesting a >> 90 * random index of an array containing ep_ro elements, for example. >> 91 * >> 92 * Returns: pseudo-random number in interval [0, ep_ro) >> 93 */ >> 94 static inline u32 prandom_u32_max(u32 ep_ro) >> 95 { >> 96 return (u32)(((u64) prandom_u32() * ep_ro) >> 32); >> 97 } >> 98 26 /* 99 /* 27 * Handle minimum values for seeds 100 * Handle minimum values for seeds 28 */ 101 */ 29 static inline u32 __seed(u32 x, u32 m) 102 static inline u32 __seed(u32 x, u32 m) 30 { 103 { 31 return (x < m) ? x + m : x; 104 return (x < m) ? x + m : x; 32 } 105 } 33 106 34 /** 107 /** 35 * prandom_seed_state - set seed for prandom_u 108 * prandom_seed_state - set seed for prandom_u32_state(). 36 * @state: pointer to state structure to recei 109 * @state: pointer to state structure to receive the seed. 37 * @seed: arbitrary 64-bit value to use as a s 110 * @seed: arbitrary 64-bit value to use as a seed. 38 */ 111 */ 39 static inline void prandom_seed_state(struct r 112 static inline void prandom_seed_state(struct rnd_state *state, u64 seed) 40 { 113 { 41 u32 i = ((seed >> 32) ^ (seed << 10) ^ 114 u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL; 42 115 43 state->s1 = __seed(i, 2U); 116 state->s1 = __seed(i, 2U); 44 state->s2 = __seed(i, 8U); 117 state->s2 = __seed(i, 8U); 45 state->s3 = __seed(i, 16U); 118 state->s3 = __seed(i, 16U); 46 state->s4 = __seed(i, 128U); 119 state->s4 = __seed(i, 128U); >> 120 PRANDOM_ADD_NOISE(state, i, 0, 0); 47 } 121 } 48 122 49 /* Pseudo random number generator from numeric 123 /* Pseudo random number generator from numerical recipes. */ 50 static inline u32 next_pseudo_random32(u32 see 124 static inline u32 next_pseudo_random32(u32 seed) 51 { 125 { 52 return seed * 1664525 + 1013904223; 126 return seed * 1664525 + 1013904223; 53 } 127 } 54 128 55 #endif 129 #endif 56 130
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.