You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
6.3 KiB
174 lines
6.3 KiB
3 months ago
|
/*
|
||
|
* The UCW Library -- Random numbers
|
||
|
*
|
||
|
* (c) 2020--2022 Pavel Charvat <pchar@ucw.cz>
|
||
|
*
|
||
|
* This software may be freely distributed and used according to the terms
|
||
|
* of the GNU Lesser General Public License.
|
||
|
*/
|
||
|
|
||
|
#ifndef _UCW_RANDOM_H
|
||
|
#define _UCW_RANDOM_H
|
||
|
|
||
|
#ifdef CONFIG_UCW_CLEAN_ABI
|
||
|
#define fastrand_new ucw_fastrand_new
|
||
|
#define fastrand_delete ucw_fastrand_delete
|
||
|
#define fastrand_set_seed ucw_fastrand_set_seed
|
||
|
#define fastrand_gen_seed_value ucw_fastrand_gen_seed_value
|
||
|
#define fastrand_gen_seed ucw_fastrand_gen_seed
|
||
|
#define fastrand_has_seed ucw_fastrand_has_seed
|
||
|
#define fastrand_reset ucw_fastrand_reset
|
||
|
#define fastrand_u32 ucw_fastrand_u32
|
||
|
#define fastrand_u64 ucw_fastrand_u64
|
||
|
#define fastrand_bits_u64 ucw_fastrand_bits_u64
|
||
|
#define fastrand_max ucw_fastrand_max
|
||
|
#define fastrand_max_u64 ucw_fastrand_max_u64
|
||
|
#define fastrand_mem ucw_fastrand_mem
|
||
|
#define fastrand_double ucw_fastrand_double
|
||
|
#define strongrand_close ucw_strongrand_close
|
||
|
#define strongrand_reset ucw_strongrand_reset
|
||
|
#define strongrand_mem ucw_strongrand_mem
|
||
|
#define strongrand_std_open ucw_strongrand_std_open
|
||
|
#define strongrand_getrandom_mem_try ucw_strongrand_getrandom_mem_try
|
||
|
#endif
|
||
|
|
||
|
/* random-fast.c */
|
||
|
|
||
|
/**
|
||
|
* Context structure for a fast pseudo-random generator.
|
||
|
* Useful for generating numbers in randomized algorithms, but not in critical things like cryptography.
|
||
|
* The library is generally thread-safe, but each context must be used by at most one thread at one time.
|
||
|
* Also be careful with fork() if you want to avoid the same numbers in subprocesses.
|
||
|
**/
|
||
|
struct fastrand;
|
||
|
|
||
|
/**
|
||
|
* Type for a seed value. Beware that some generators are only able to use the lowest 32 bits.
|
||
|
**/
|
||
|
typedef u64 fastrand_seed_t;
|
||
|
|
||
|
/**
|
||
|
* Allocate a new context. Should be paired with fastrand_delete().
|
||
|
* Don't forget to supply a seed before started to read randomness.
|
||
|
**/
|
||
|
struct fastrand *fastrand_new(void);
|
||
|
void fastrand_delete(struct fastrand *c);
|
||
|
|
||
|
/** (Re)seed the context with given value. **/
|
||
|
void fastrand_set_seed(struct fastrand *c, fastrand_seed_t seed);
|
||
|
|
||
|
/**
|
||
|
* Generate a seed for fastrand_set_seed().
|
||
|
*
|
||
|
* Since glibc 2.25 and kernel 3.17, we use getrandom() syscall
|
||
|
* to read kernel's urandom.
|
||
|
*
|
||
|
* Otherwise we mix these things:
|
||
|
* -- current time
|
||
|
* -- process id to deal with frequent fork() or startups
|
||
|
* -- counter to deal with multiple contexts, for example in threaded application
|
||
|
**/
|
||
|
fastrand_seed_t fastrand_gen_seed_value(void);
|
||
|
|
||
|
/** (Re)seed the context with fastrand_gen_seed_value(). **/
|
||
|
fastrand_seed_t fastrand_gen_seed(struct fastrand *c);
|
||
|
|
||
|
/** Is the context seeded? **/
|
||
|
bool fastrand_has_seed(struct fastrand *c);
|
||
|
|
||
|
/** Reset the context to its initial state. Useful after a fork() to assert forgotten reseed. **/
|
||
|
void fastrand_reset(struct fastrand *c);
|
||
|
|
||
|
/** Uniformly generate 32 random bits. **/
|
||
|
u32 fastrand_u32(struct fastrand *c);
|
||
|
|
||
|
/** Uniformly generate 64 random bits. **/
|
||
|
u64 fastrand_u64(struct fastrand *c);
|
||
|
|
||
|
/** Uniformly generate [0, 64] random bits. **/
|
||
|
u64 fastrand_bits_u64(struct fastrand *c, uint bits);
|
||
|
|
||
|
/** Uniformly generate [0, 8*sizeof(uint)] random bits. **/
|
||
|
static inline uint fastrand_bits(struct fastrand *c, uint bits)
|
||
|
{
|
||
|
return fastrand_bits_u64(c, bits);
|
||
|
}
|
||
|
|
||
|
/** Uniformly generate a random number from range [0, bound-1], where @bound is [1, UINT_MAX]. **/
|
||
|
uint fastrand_max(struct fastrand *c, uint bound);
|
||
|
|
||
|
/** Uniformly generate a random number from range [0, bound-1], where @bound is [1, UINT64_MAX]. **/
|
||
|
u64 fastrand_max_u64(struct fastrand *c, u64 bound);
|
||
|
|
||
|
/** Generate @size random bytes. **/
|
||
|
void fastrand_mem(struct fastrand *c, void *ptr, size_t size);
|
||
|
|
||
|
/** Uniformly generate a random number from range [0.0, 1.0) + possible inaccuracies from basic floating point operations. **/
|
||
|
double fastrand_double(struct fastrand *c);
|
||
|
|
||
|
/* random-strong.c */
|
||
|
|
||
|
/**
|
||
|
* Context structure for a strong random generator.
|
||
|
* Useful for things like generating random ids or cryptography.
|
||
|
* The library is generally thread-safe, but each context must be used by at most one thread at one time.
|
||
|
*
|
||
|
* Also be careful with fork(). Unless said otherwise, it's forbidden to use the context
|
||
|
* in a forked child, we can even assert changes of pid. See strongrand_reset() if you
|
||
|
* need that.
|
||
|
**/
|
||
|
struct strongrand {
|
||
|
const char *name; /* (mandatory) Context name for logging. */
|
||
|
void (*read)(struct strongrand *sr, byte *ptr, int size); /* (mandatory) Generate @size random bytes. */
|
||
|
void (*close)(struct strongrand *sr); /* Called from strongrand_close(). */
|
||
|
void (*reset)(struct strongrand *sr); /* Called from strongrand_reset(). */
|
||
|
};
|
||
|
|
||
|
/** Close a previously opened context. **/
|
||
|
void strongrand_close(struct strongrand *c);
|
||
|
|
||
|
/**
|
||
|
* If you want to use the same context in multiple forked subprocesses, you must
|
||
|
* call this function after the fork() to flush any buffered randomness.
|
||
|
* Some future back-ends could use it for even more things, for example
|
||
|
* to re-connect somewhere.
|
||
|
**/
|
||
|
void strongrand_reset(struct strongrand *sr);
|
||
|
|
||
|
/** Generate @size random bytes. **/
|
||
|
void strongrand_mem(struct strongrand *c, void *ptr, size_t size);
|
||
|
|
||
|
/**
|
||
|
* Open kernel's random generator.
|
||
|
* Requires exactly one of these flags, among others:
|
||
|
* -- STRONGRAND_STD_URANDOM
|
||
|
* -- STRONGRAND_STD_RANDOM
|
||
|
*
|
||
|
* Since glibc 2.25 and kernel 3.17, we use getrandom() syscall,
|
||
|
* otherwise we open and read from "/dev/[u]random" device.
|
||
|
*
|
||
|
* @buf_size can be 0 for unbuffered reading.
|
||
|
*
|
||
|
* STRONGRAND_STD_x_RESET flags are only useful for buffered reading.
|
||
|
*
|
||
|
* If at least one of the following conditions are met, strongrand_reset()
|
||
|
* after fork() is not necessary:
|
||
|
* -- zero @buf_size
|
||
|
* -- STRONGRAND_STD_AUTO_RESET flag
|
||
|
* -- no read since open or last reset (empty buffer)
|
||
|
**/
|
||
|
struct strongrand *strongrand_std_open(uint flags, uint buf_size);
|
||
|
|
||
|
enum strongrand_std_flags {
|
||
|
STRONGRAND_STD_URANDOM = 0x1, // Use kernel's "urandom" source.
|
||
|
STRONGRAND_STD_RANDOM = 0x2, // Use kernel's "random" source.
|
||
|
STRONGRAND_STD_DELAYED = 0x4, // Delay non-trivial initializations like opening file descriptor to first read.
|
||
|
STRONGRAND_STD_AUTO_RESET = 0x8, // Automatically do strongrand_reset() after changes of getpid(); adds overhead to each read.
|
||
|
STRONGRAND_STD_ASSERT_RESET = 0x10, // Assert correct usage of strongrand_reset() after changes of getpid(); for debugging.
|
||
|
};
|
||
|
|
||
|
// Internals
|
||
|
bool strongrand_getrandom_mem_try(void *buf, size_t size);
|
||
|
|
||
|
#endif
|