From 1d6e593abad4f95a8ffec132ec76e7da83d0dd8b Mon Sep 17 00:00:00 2001 From: Alula Date: Fri, 18 Sep 2026 07:25:48 +0200 Subject: [PATCH] kern: use CTR_DRBG from vapours --- .../mesosphere/kern_k_system_control_base.hpp | 14 --- .../source/kern_k_system_control_base.cpp | 105 ++++++------------ 2 files changed, 36 insertions(+), 83 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp index cc8f0f317..95d601959 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_system_control_base.hpp @@ -33,24 +33,10 @@ namespace ams::kern { class KResourceLimit; - struct CtrDrbgContext { - u8 v[16]; - u8 key[16]; - u8 seed[32]; - u8 temp[32]; - u32 reseed_counter; - u8 output[128]; - u32 remaining; - }; - class KSystemControlBase { public: /* This can be overridden as needed. */ static constexpr size_t SecureAppletMemorySize = 0; - protected: - static constinit inline bool s_uninitialized_random_generator{true}; - static constinit inline CtrDrbgContext s_random_generator{}; - static constinit inline KSpinLock s_random_lock; private: /* Randomness helpers. */ static void InitializeRandomGenerator(const void *seed, size_t size); diff --git a/libraries/libmesosphere/source/kern_k_system_control_base.cpp b/libraries/libmesosphere/source/kern_k_system_control_base.cpp index ffe172846..c92bbe60e 100644 --- a/libraries/libmesosphere/source/kern_k_system_control_base.cpp +++ b/libraries/libmesosphere/source/kern_k_system_control_base.cpp @@ -14,7 +14,8 @@ * along with this program. If not, see . */ #include -#include +#include +#include #if defined(ATMOSPHERE_ARCH_ARM64) #include #endif @@ -46,33 +47,19 @@ namespace ams::kern { } }; - ALWAYS_INLINE void CtrDrbgIncrementCounter(u8 *v) { - for (size_t i = 16; i > 0; --i) { - if ((++v[i - 1]) != 0) { - break; - } - } - } + using RandomGenerator = ::ams::crypto::impl::CtrDrbg<::ams::crypto::AesEncryptor128, 16, false>; - void CtrDrbgUpdate(CtrDrbgContext &ctx, const u8 *data) { - /* Initialize the block cipher with the current key. */ - ams::crypto::impl::AesImpl<16> aes; - aes.Initialize(ctx.key, sizeof(ctx.key), true); + constexpr size_t RandomGeneratorOutputSize = 8 * RandomGenerator::OutSize; + constexpr u32 RandomGeneratorOutputCount = RandomGeneratorOutputSize / sizeof(u32); - /* Generate two blocks of new key/counter material. */ - CtrDrbgIncrementCounter(ctx.v); - aes.EncryptBlock(ctx.temp + 0, 16, ctx.v, 16); - CtrDrbgIncrementCounter(ctx.v); - aes.EncryptBlock(ctx.temp + 16, 16, ctx.v, 16); + constinit util::TypedStorage s_random_generator = {}; + constinit bool s_uninitialized_random_generator = true; + constinit u8 s_random_output[RandomGeneratorOutputSize] = {}; + constinit u32 s_random_remaining = 0; + constinit KSpinLock s_random_lock; - /* Mix in the provided data. */ - for (size_t i = 0; i < sizeof(ctx.temp); ++i) { - ctx.temp[i] ^= data[i]; - } - - /* Update the key and counter. */ - std::memcpy(ctx.key, ctx.temp, sizeof(ctx.key)); - std::memcpy(ctx.v, ctx.temp + sizeof(ctx.key), sizeof(ctx.v)); + void GenerateRandomSeed(void *dst, size_t size) { + KSystemControl::GenerateRandomBytesForUninitialized(dst, size); } } @@ -255,72 +242,52 @@ namespace ams::kern { /* Randomness helpers. Assume the caller holds the random lock. */ void KSystemControlBase::InitializeRandomGenerator(const void *seed, size_t size) { - MESOSPHERE_ASSERT(size == sizeof(s_random_generator.seed)); + MESOSPHERE_ASSERT(size == RandomGenerator::SeedSize); KScopedFpuEnable fp_enabled; - auto &ctx = s_random_generator; - /* Zero the counter and key, then derive the initial state from the seed. */ - std::memset(ctx.v, 0, sizeof(ctx.v)); - std::memset(ctx.key, 0, sizeof(ctx.key)); - std::memcpy(ctx.seed, seed, sizeof(ctx.seed)); + /* Construct the generator, and derive the initial state from the seed. */ + util::ConstructAt(s_random_generator); + util::GetReference(s_random_generator).Initialize(seed, size, nullptr, 0, nullptr, 0); - CtrDrbgUpdate(ctx, ctx.seed); - - ctx.reseed_counter = 1; - ctx.remaining = 0; + s_random_remaining = 0; } void KSystemControlBase::ReseedRandomGeneratorInternal() { KScopedFpuEnable fp_enabled; - auto &ctx = s_random_generator; /* Pull fresh entropy, then derive a new state from it. */ - KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed)); - CtrDrbgUpdate(ctx, ctx.seed); + u8 seed[RandomGenerator::SeedSize]; + GenerateRandomSeed(seed, sizeof(seed)); + util::GetReference(s_random_generator).Reseed(seed, sizeof(seed), nullptr, 0); - ctx.remaining = 0; - ctx.reseed_counter = 1; + s_random_remaining = 0; } u32 KSystemControlBase::GenerateRandomU32() { - auto &ctx = s_random_generator; - - if (ctx.remaining == 0) { + if (s_random_remaining == 0) { KScopedFpuEnable fp_enabled; - /* Reseed if we've exhausted this generation's entropy, otherwise use zero additional input. */ - if (ctx.reseed_counter <= 0x7FFFFFF0) { - std::memset(ctx.seed, 0, sizeof(ctx.seed)); - } else { - KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed)); - CtrDrbgUpdate(ctx, ctx.seed); - ctx.remaining = 0; - std::memset(ctx.seed, 0, sizeof(ctx.seed)); - ctx.reseed_counter = 1; + auto &drbg = util::GetReference(s_random_generator); + + /* Derive the next state, or reseed if we've exhausted this generation's entropy. */ + if (AMS_UNLIKELY(!drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0))) { + u8 seed[RandomGenerator::SeedSize]; + GenerateRandomSeed(seed, sizeof(seed)); + drbg.Reseed(seed, sizeof(seed), nullptr, 0); + + MESOSPHERE_ABORT_UNLESS(drbg.Generate(s_random_output, sizeof(s_random_output), nullptr, 0)); } - /* Generate eight blocks of output. */ - ams::crypto::impl::AesImpl<16> aes; - aes.Initialize(ctx.key, sizeof(ctx.key), true); - for (size_t i = 0; i < 8; ++i) { - CtrDrbgIncrementCounter(ctx.v); - aes.EncryptBlock(ctx.output + 16 * i, 16, ctx.v, 16); - } - - /* Derive the next state. */ - CtrDrbgUpdate(ctx, ctx.seed); - - ++ctx.reseed_counter; - ctx.remaining = 32; + s_random_remaining = RandomGeneratorOutputCount; } /* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */ - const size_t index = 32 - ctx.remaining; + const size_t index = RandomGeneratorOutputCount - s_random_remaining; u32 value; - std::memcpy(std::addressof(value), ctx.output + 4 * index, sizeof(value)); - std::memset(ctx.output + 4 * index, 0, sizeof(value)); - --ctx.remaining; + std::memcpy(std::addressof(value), s_random_output + sizeof(value) * index, sizeof(value)); + std::memset(s_random_output + sizeof(value) * index, 0, sizeof(value)); + --s_random_remaining; return value; }