]> mj.ucw.cz Git - libucw.git/blob - ucw/random.h
Random: Detect and use getrandom() to seed fastrand.
[libucw.git] / ucw / random.h
1 /*
2  *      The UCW Library -- Random numbers
3  *
4  *      (c) 2020--2022 Pavel Charvat <pchar@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #ifndef _UCW_RANDOM_H
11 #define _UCW_RANDOM_H
12
13 #ifdef CONFIG_UCW_CLEAN_ABI
14 #define fastrand_new ucw_fastrand_new
15 #define fastrand_delete ucw_fastrand_delete
16 #define fastrand_set_seed ucw_fastrand_set_seed
17 #define fastrand_gen_seed_value ucw_fastrand_gen_seed_value
18 #define fastrand_gen_seed ucw_fastrand_gen_seed
19 #define fastrand_has_seed ucw_fastrand_has_seed
20 #define fastrand_reset ucw_fastrand_reset
21 #define fastrand_u32 ucw_fastrand_u32
22 #define fastrand_u64 ucw_fastrand_u64
23 #define fastrand_bits_u64 ucw_fastrand_bits_u64
24 #define fastrand_max ucw_fastrand_max
25 #define fastrand_max_u64 ucw_fastrand_max_u64
26 #define fastrand_mem ucw_fastrand_mem
27 #define fastrand_double ucw_fastrand_double
28 #define strongrand_getrandom_mem_try ucw_strongrand_getrandom_mem_try
29 #endif
30
31 /* random-fast.c */
32
33 /**
34  * Context structure for a fast pseudo-random generator.
35  * Useful for generating numbers in randomized algorithms, but not in critical things like cryptography.
36  * The library is generally thread-safe, but each context must be used by at most one thread at one time.
37  * Also be careful with fork() if you want to avoid the same numbers in subprocesses.
38  **/
39 struct fastrand;
40
41 /**
42  * Type for a seed value. Beware that some generators are only able to use the lowest 32 bits.
43  **/
44 typedef u64 fastrand_seed_t;
45
46 /**
47  * Allocate a new context. Should be paired with fastrand_delete().
48  * Don't forget to supply a seed before started to read randomness.
49  **/
50 struct fastrand *fastrand_new(void);
51 void fastrand_delete(struct fastrand *c);
52
53 /** (Re)seed the context with given value. **/
54 void fastrand_set_seed(struct fastrand *c, fastrand_seed_t seed);
55
56 /**
57  * Generate a seed for fastrand_set_seed().
58  *
59  * Since glibc 2.25 and kernel 3.17, we use getrandom() syscall
60  * to read kernel's urandom.
61  *
62  * Otherwise we mix these things:
63  * -- current time
64  * -- process id to deal with frequent fork() or startups
65  * -- counter to deal with multiple contexts, for example in threaded application
66  **/
67 fastrand_seed_t fastrand_gen_seed_value(void);
68
69 /** (Re)seed the context with fastrand_gen_seed_value(). **/
70 fastrand_seed_t fastrand_gen_seed(struct fastrand *c);
71
72 /** Is the context seeded? **/
73 bool fastrand_has_seed(struct fastrand *c);
74
75 /** Reset the context to its initial state. Useful after a fork() to assert forgotten reseed. **/
76 void fastrand_reset(struct fastrand *c);
77
78 /** Uniformly generate 32 random bits. **/
79 u32 fastrand_u32(struct fastrand *c);
80
81 /** Uniformly generate 64 random bits. **/
82 u64 fastrand_u64(struct fastrand *c);
83
84 /** Uniformly generate [0, 64] random bits. **/
85 u64 fastrand_bits_u64(struct fastrand *c, uint bits);
86
87 /** Uniformly generate [0, 8*sizeof(uint)] random bits. **/
88 static inline uint fastrand_bits(struct fastrand *c, uint bits)
89 {
90   return fastrand_bits_u64(c, bits);
91 }
92
93 /** Uniformly generate a random number from range [0, bound-1], where @bound is [1, UINT_MAX]. **/
94 uint fastrand_max(struct fastrand *c, uint bound);
95
96 /** Uniformly generate a random number from range [0, bound-1], where @bound is [1, UINT64_MAX]. **/
97 u64 fastrand_max_u64(struct fastrand *c, u64 bound);
98
99 /** Generate @size random bytes. **/
100 void fastrand_mem(struct fastrand *c, void *ptr, size_t size);
101
102 /** Uniformly generate a random number from range [0.0, 1.0) + possible inaccuracies from basic floating point operations. **/
103 double fastrand_double(struct fastrand *c);
104
105 /* random-strong.c */
106
107 /* FIXME: interface for strong randomness */
108
109 // Internals
110 bool strongrand_getrandom_mem_try(void *buf, size_t size);
111
112 #endif