From e90b72ec3082588b296956730bd2930cf8d5d671 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Fri, 10 Jul 2026 11:31:46 +0800 Subject: refactor: promote new architecture to repository root Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior. --- lib/random.cc | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 lib/random.cc (limited to 'lib/random.cc') diff --git a/lib/random.cc b/lib/random.cc new file mode 100644 index 0000000..428c75c --- /dev/null +++ b/lib/random.cc @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright (C) 2026 Richard Qin */ + +#include +#include +#include + +#include + +/* + * Early Boot PRNG (xoshiro256**) + * State size: 256 bits (4 * 64-bit words) + * Extremely fast, excellent statistical properties. + */ + +static uint64 g_state[4]; +static bool g_initialized = false; +static uint64 g_init_seed = 0; +static RandomSeedSource g_seed_source = RandomSeedSource::Unknown; + +static inline uint64 rotl(const uint64 x, int k) { + return (x << k) | (x >> (64 - k)); +} + +/* SplitMix64 used to initialize xoshiro state from a single 64-bit seed */ +static uint64 splitmix64(uint64& state) { + uint64 z = (state += 0x9e3779b97f4a7c15ULL); + z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL; + z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL; + return z ^ (z >> 31); +} + +void random_early_init(uint64 seed) +{ + if (g_initialized) return; + + RandomSeedSource source = RandomSeedSource::Unknown; + + /* If seed is 0 (not provided by bootloader), try hardware */ + if (seed == 0) { + uint64 hw_val; + if (arch::get_hw_random(hw_val)) { + seed = hw_val; + source = RandomSeedSource::HwRandom; + } else { + /* Fallback: use boot cycles mixed with a constant */ + seed = arch::get_cycles() ^ 0xdeadbeefbadc0ffeULL; + source = RandomSeedSource::CycleFallback; + } + } else { + source = RandomSeedSource::FdtProvided; + } + + uint64 sm_state = seed; + g_state[0] = splitmix64(sm_state); + g_state[1] = splitmix64(sm_state); + g_state[2] = splitmix64(sm_state); + g_state[3] = splitmix64(sm_state); + + g_init_seed = seed; + g_seed_source = source; + g_initialized = true; + kprintf("[random] early PRNG initialized, seed=0x%llx, source=%s\n", + seed, random_seed_source_name(source)); +} + +uint64 get_random_u64() +{ + if (!g_initialized) { + random_early_init(0); + } + + const uint64 result = rotl(g_state[1] * 5, 7) * 9; + + const uint64 t = g_state[1] << 17; + + g_state[2] ^= g_state[0]; + g_state[3] ^= g_state[1]; + g_state[1] ^= g_state[2]; + g_state[0] ^= g_state[3]; + + g_state[2] ^= t; + g_state[3] = rotl(g_state[3], 45); + + /* Mix with current cycles for slight additional unpredictability */ + return result ^ arch::get_cycles(); +} + +uint32 get_random_u32() +{ + return static_cast(get_random_u64() >> 32); +} + +void get_random_bytes(void* buf, size_t len) +{ + uint8* p = static_cast(buf); + while (len >= 8) { + uint64 val = get_random_u64(); + for (int i = 0; i < 8; i++) { + p[i] = (val >> (i * 8)) & 0xFF; + } + p += 8; + len -= 8; + } + if (len > 0) { + uint64 val = get_random_u64(); + for (size_t i = 0; i < len; i++) { + p[i] = (val >> (i * 8)) & 0xFF; + } + } +} + +void add_device_randomness(const void* buf, size_t len) +{ + /* + * For now, just mix into the xoshiro state using a simple XOR. + * In the future, this will feed the CSPRNG entropy pool. + */ + const uint8* p = static_cast(buf); + uint64 mix = arch::get_cycles(); + for (size_t i = 0; i < len; i++) { + mix = (mix << 5) ^ (mix >> 59) ^ p[i]; + } + + g_state[0] ^= mix; + g_state[1] ^= arch::get_cycles(); +} + +RandomSeedSource random_early_seed_source() +{ + return g_seed_source; +} + +uint64 random_early_seed_value() +{ + return g_init_seed; +} + +const char* random_seed_source_name(RandomSeedSource source) +{ + switch (source) { + case RandomSeedSource::FdtProvided: + return "fdt"; + case RandomSeedSource::HwRandom: + return "hw"; + case RandomSeedSource::CycleFallback: + return "cycle"; + case RandomSeedSource::Unknown: + default: + return "unknown"; + } +} -- cgit v1.2.3