From 7eaefa5aa6b85f5f7720ee823da2969280994fcb Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Boric Date: Sun, 24 Jan 2021 18:17:54 +0100 Subject: [PATCH] Kernel: Make use of interrupts as an entropy source Booting old computers without RDRAND/RDSEED and without a disk makes the system severely starved for entropy. Uses interrupts as a source to side-step that issue. Also warn whenever the system is starved of entropy, because that's a non-obvious failure mode. --- Kernel/Arch/i386/CPU.cpp | 4 ++++ Kernel/Random.cpp | 3 ++- Kernel/Random.h | 11 ++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index da850af1c3..9a9e1a29af 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,8 @@ static Descriptor s_idt[256]; static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_COUNT]; +static EntropySource s_entropy_source_interrupts{EntropySource::Static::Interrupts}; + // The compiler can't see the calls to these functions inside assembly. // Declare them, to avoid dead code warnings. extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread); @@ -709,6 +712,7 @@ void handle_interrupt(TrapFrame* trap) auto& regs = *trap->regs; ASSERT(regs.isr_number >= IRQ_VECTOR_BASE && regs.isr_number <= (IRQ_VECTOR_BASE + GENERIC_INTERRUPT_HANDLERS_COUNT)); u8 irq = (u8)(regs.isr_number - 0x50); + s_entropy_source_interrupts.add_random_event(irq); auto* handler = s_interrupt_handler[irq]; ASSERT(handler); handler->increment_invoking_counter(); diff --git a/Kernel/Random.cpp b/Kernel/Random.cpp index 12ec58fca6..3230c03416 100644 --- a/Kernel/Random.cpp +++ b/Kernel/Random.cpp @@ -69,6 +69,7 @@ KernelRng::KernelRng() void KernelRng::wait_for_entropy() { if (!resource().is_ready()) { + dbgln("Entropy starvation..."); m_seed_queue.wait_on({}, "KernelRng"); } } @@ -80,7 +81,7 @@ void KernelRng::wake_if_ready() } } -size_t EntropySource::next_source { 0 }; +size_t EntropySource::next_source { static_cast(EntropySource::Static::MaxHardcodedSourceIndex) }; void get_good_random_bytes(u8* buffer, size_t buffer_size) { diff --git a/Kernel/Random.h b/Kernel/Random.h index db4c29b4c3..298c2407aa 100644 --- a/Kernel/Random.h +++ b/Kernel/Random.h @@ -147,11 +147,21 @@ class EntropySource { }; public: + enum class Static : size_t { + Interrupts, + MaxHardcodedSourceIndex, + }; + EntropySource() : m_source(next_source++) { } + EntropySource(Static hardcoded_source) + : m_source(static_cast(hardcoded_source)) + { + } + template void add_random_event(const T& event_data) { @@ -166,7 +176,6 @@ private: static size_t next_source; size_t m_pool { 0 }; size_t m_source; - Lock m_lock; }; // NOTE: These API's are primarily about expressing intent/needs in the calling code.