32#include <sys/kernel.h>
33#include <sys/libkern.h>
34#include <sys/linker.h>
36#include <sys/malloc.h>
39#include <sys/random.h>
43#include <machine/cpu.h>
45#include <crypto/chacha20/chacha.h>
46#include <crypto/sha2/sha256.h>
47#include <dev/random/randomdev.h>
48#ifdef RANDOM_FENESTRASX
49#include <dev/random/fenestrasX/fx_pub.h>
52#define CHACHA20_RESEED_BYTES 65536
53#define CHACHA20_RESEED_SECONDS 300
54#define CHACHA20_KEYBYTES 32
55#define CHACHA20_BUFFER_SIZE 64
59#ifndef RANDOM_FENESTRASX
63MALLOC_DEFINE(M_CHACHA20RANDOM,
"chacha20random",
"chacha20random structures");
70 struct chacha_ctx
ctx;
71#ifdef RANDOM_FENESTRASX
72 uint64_t seed_version;
78#define CHACHA20_FOREACH(_chacha20) \
79 for (_chacha20 = &chacha20inst[0]; \
80 _chacha20 <= &chacha20inst[mp_maxid]; \
89 struct timeval tv_now;
91#ifdef RANDOM_FENESTRASX
92 uint64_t seed_version;
95 if (__predict_false(random_bypass_before_seeding && !is_random_seeded())) {
100 if (!arc4random_bypassed_before_seeding) {
101 arc4random_bypassed_before_seeding =
true;
102 if (!random_bypass_disable_warnings)
103 printf(
"arc4random: WARNING: initial seeding "
104 "bypassed the cryptographic random device "
105 "because it was not yet seeded and the "
106 "knob 'bypass_before_seeding' was "
116 kmsan_mark(key,
sizeof(key), KMSAN_STATE_INITED);
119 cc = get_cyclecount();
121 SHA256_Update(&
ctx, key,
sizeof(key));
122 SHA256_Update(&
ctx, &cc,
sizeof(cc));
123 fver = __FreeBSD_version;
124 SHA256_Update(&
ctx, &fver,
sizeof(fver));
125 _Static_assert(
sizeof(key) == SHA256_DIGEST_LENGTH,
126 "make sure 256 bits is still 256 bits");
127 SHA256_Final(key, &
ctx);
130#ifdef RANDOM_FENESTRASX
145 getmicrouptime(&tv_now);
146 mtx_lock(&chacha20->
mtx);
148 chacha_ivsetup(&chacha20->
ctx, (u_char *)&tv_now.tv_sec, (u_char *)&tv_now.tv_usec);
152#ifdef RANDOM_FENESTRASX
153 chacha20->seed_version = seed_version;
155 mtx_unlock(&chacha20->
mtx);
167 M_CHACHA20RANDOM, M_NOWAIT | M_ZERO);
168 KASSERT(
chacha20inst != NULL, (
"chacha20_init: memory allocation error"));
171 mtx_init(&chacha20->
mtx,
"chacha20_mtx", NULL, MTX_DEF);
187 mtx_destroy(&chacha20->
mtx);
204#ifdef RANDOM_FENESTRASX
205 if (__predict_false(reseed))
207 if (__predict_false(reseed ||
220 mtx_lock(&chacha20->
mtx);
221#ifdef RANDOM_FENESTRASX
223 atomic_load_acq_64(&fxrng_root_generation) != chacha20->seed_version
225 mtx_unlock(&chacha20->
mtx);
227 mtx_lock(&chacha20->
mtx);
234 chacha_encrypt_bytes(&chacha20->
ctx, chacha20->
m_buffer, p, length);
239 mtx_unlock(&chacha20->
mtx);
241 mtx_lock(&chacha20->
mtx);
244 mtx_unlock(&chacha20->
mtx);
uint32_t arc4random(void)
SYSINIT(chacha20, SI_SUB_LOCK, SI_ORDER_ANY, chacha20_init, NULL)
MALLOC_DEFINE(M_CHACHA20RANDOM, "chacha20random", "chacha20random structures")
#define CHACHA20_KEYBYTES
static struct chacha20_s * chacha20inst
#define CHACHA20_BUFFER_SIZE
CTASSERT(CHACHA20_KEYBYTES *8 >=CHACHA_MINKEYLEN)
#define CHACHA20_RESEED_BYTES
#define CHACHA20_FOREACH(_chacha20)
static void chacha20_randomstir(struct chacha20_s *chacha20)
void arc4rand(void *ptr, u_int len, int reseed)
static void chacha20_init(void)
SYSUNINIT(chacha20, SI_SUB_LOCK, SI_ORDER_ANY, chacha20_uninit, NULL)
struct chacha20_s __aligned(CACHE_LINE_SIZE)
int arc4rand_iniseed_state
void arc4random_buf(void *ptr, size_t len)
#define CHACHA20_RESEED_SECONDS
static void chacha20_uninit(void)
void explicit_bzero(void *buf, size_t len)
uint8_t m_buffer[CHACHA20_BUFFER_SIZE]