summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Elliott <pelliott@ualberta.ca>2020-06-24 14:07:28 -0600
committerAndreas Kling <kling@serenityos.org>2020-06-25 21:05:40 +0200
commitaf0b2d1d86761dd7dc89bb605794093968a0a74f (patch)
tree3c4cc42287c297f59d0229657039a796895a337f
parent2e8cfe5435f806538fe680235b2e9792ca34b201 (diff)
downloadserenity-af0b2d1d86761dd7dc89bb605794093968a0a74f.zip
Kernel: Harvest randomness from various drivers
Random now gets entropy from the following drivers: - KeyboardDevice - PATAChannel - PS2MouseDevice - E1000NetworkAdapter - RTL8139NetworkAdapter Of these devices, PS2MouseDevice and PATAChannel provide the vast majority of the entropy.
-rw-r--r--Kernel/Devices/KeyboardDevice.cpp2
-rw-r--r--Kernel/Devices/KeyboardDevice.h2
-rw-r--r--Kernel/Devices/PATAChannel.cpp5
-rw-r--r--Kernel/Devices/PATAChannel.h2
-rw-r--r--Kernel/Devices/PS2MouseDevice.cpp3
-rw-r--r--Kernel/Devices/PS2MouseDevice.h2
-rw-r--r--Kernel/Net/E1000NetworkAdapter.cpp3
-rw-r--r--Kernel/Net/E1000NetworkAdapter.h4
-rw-r--r--Kernel/Net/RTL8139NetworkAdapter.cpp2
-rw-r--r--Kernel/Net/RTL8139NetworkAdapter.h4
-rw-r--r--Kernel/Random.cpp15
-rw-r--r--Kernel/Random.h34
12 files changed, 71 insertions, 7 deletions
diff --git a/Kernel/Devices/KeyboardDevice.cpp b/Kernel/Devices/KeyboardDevice.cpp
index 01a34c8534..20e26da491 100644
--- a/Kernel/Devices/KeyboardDevice.cpp
+++ b/Kernel/Devices/KeyboardDevice.cpp
@@ -287,6 +287,8 @@ void KeyboardDevice::handle_irq(const RegisterState&)
u8 ch = raw & 0x7f;
bool pressed = !(raw & 0x80);
+ m_entropy_source.add_random_event(raw);
+
if (raw == 0xe0) {
m_has_e0_prefix = true;
return;
diff --git a/Kernel/Devices/KeyboardDevice.h b/Kernel/Devices/KeyboardDevice.h
index acc2297eb7..f35ffd9621 100644
--- a/Kernel/Devices/KeyboardDevice.h
+++ b/Kernel/Devices/KeyboardDevice.h
@@ -32,6 +32,7 @@
#include <Kernel/Devices/CharacterDevice.h>
#include <Kernel/Interrupts/IRQHandler.h>
#include <Kernel/KeyCode.h>
+#include <Kernel/Random.h>
#include <LibKeyboard/CharacterMap.h>
namespace Kernel {
@@ -82,6 +83,7 @@ private:
bool m_caps_lock_on { false };
bool m_num_lock_on { false };
bool m_has_e0_prefix { false };
+ EntropySource m_entropy_source;
Keyboard::CharacterMap m_character_map = Keyboard::CharacterMap("en");
};
diff --git a/Kernel/Devices/PATAChannel.cpp b/Kernel/Devices/PATAChannel.cpp
index 06b88afb16..1fc75745bd 100644
--- a/Kernel/Devices/PATAChannel.cpp
+++ b/Kernel/Devices/PATAChannel.cpp
@@ -29,9 +29,9 @@
#include <Kernel/Devices/PATAChannel.h>
#include <Kernel/Devices/PATADiskDevice.h>
#include <Kernel/FileSystem/ProcFS.h>
+#include <Kernel/IO.h>
#include <Kernel/Process.h>
#include <Kernel/VM/MemoryManager.h>
-#include <Kernel/IO.h>
namespace Kernel {
@@ -186,6 +186,9 @@ void PATAChannel::handle_irq(const RegisterState&)
// FIXME: We might get random interrupts due to malfunctioning hardware, so we should check that we actually requested something to happen.
u8 status = m_io_base.offset(ATA_REG_STATUS).in<u8>();
+
+ m_entropy_source.add_random_event(status);
+
if (status & ATA_SR_ERR) {
print_ide_status(status);
m_device_error = m_io_base.offset(ATA_REG_ERROR).in<u8>();
diff --git a/Kernel/Devices/PATAChannel.h b/Kernel/Devices/PATAChannel.h
index 09eed4216c..60ed95d6c1 100644
--- a/Kernel/Devices/PATAChannel.h
+++ b/Kernel/Devices/PATAChannel.h
@@ -44,6 +44,7 @@
#include <Kernel/PCI/Access.h>
#include <Kernel/PCI/Device.h>
#include <Kernel/PhysicalAddress.h>
+#include <Kernel/Random.h>
#include <Kernel/VM/PhysicalPage.h>
#include <Kernel/WaitQueue.h>
@@ -103,6 +104,7 @@ private:
RefPtr<PhysicalPage> m_dma_buffer_page;
IOAddress m_bus_master_base;
Lockable<bool> m_dma_enabled;
+ EntropySource m_entropy_source;
RefPtr<PATADiskDevice> m_master;
RefPtr<PATADiskDevice> m_slave;
diff --git a/Kernel/Devices/PS2MouseDevice.cpp b/Kernel/Devices/PS2MouseDevice.cpp
index e673c02fbd..56852537cd 100644
--- a/Kernel/Devices/PS2MouseDevice.cpp
+++ b/Kernel/Devices/PS2MouseDevice.cpp
@@ -81,6 +81,7 @@ void PS2MouseDevice::handle_irq(const RegisterState&)
if (backdoor->vmmouse_is_absolute()) {
IO::in8(I8042_BUFFER);
auto packet = backdoor->receive_mouse_packet();
+ m_entropy_source.add_random_event(packet);
if (packet.has_value())
m_queue.enqueue(packet.value());
return;
@@ -99,6 +100,8 @@ void PS2MouseDevice::handle_irq(const RegisterState&)
#ifdef PS2MOUSE_DEBUG
dbg() << "PS2Mouse: " << m_data[1] << ", " << m_data[2] << " " << ((m_data[0] & 1) ? "Left" : "") << " " << ((m_data[0] & 2) ? "Right" : "") << " (buffered: " << m_queue.size() << ")";
#endif
+ m_entropy_source.add_random_event(*(u32*)m_data);
+
parse_data_packet();
};
diff --git a/Kernel/Devices/PS2MouseDevice.h b/Kernel/Devices/PS2MouseDevice.h
index 5ed62b52db..cfb2557f85 100644
--- a/Kernel/Devices/PS2MouseDevice.h
+++ b/Kernel/Devices/PS2MouseDevice.h
@@ -30,6 +30,7 @@
#include <Kernel/Devices/CharacterDevice.h>
#include <Kernel/Interrupts/IRQHandler.h>
#include <Kernel/MousePacket.h>
+#include <Kernel/Random.h>
namespace Kernel {
@@ -77,6 +78,7 @@ private:
u8 m_data[4];
bool m_has_wheel { false };
bool m_has_five_buttons { false };
+ EntropySource m_entropy_source;
};
}
diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp
index e8619d6770..3dd74a6cb9 100644
--- a/Kernel/Net/E1000NetworkAdapter.cpp
+++ b/Kernel/Net/E1000NetworkAdapter.cpp
@@ -204,6 +204,9 @@ void E1000NetworkAdapter::handle_irq(const RegisterState&)
out32(REG_INTERRUPT_MASK_CLEAR, 0xffffffff);
u32 status = in32(REG_INTERRUPT_CAUSE_READ);
+
+ m_entropy_source.add_random_event(status);
+
if (status & 4) {
u32 flags = in32(REG_CTRL);
out32(REG_CTRL, flags | ECTRL_SLU);
diff --git a/Kernel/Net/E1000NetworkAdapter.h b/Kernel/Net/E1000NetworkAdapter.h
index 96214e9d6d..fd5f864879 100644
--- a/Kernel/Net/E1000NetworkAdapter.h
+++ b/Kernel/Net/E1000NetworkAdapter.h
@@ -28,11 +28,12 @@
#include <AK/NonnullOwnPtrVector.h>
#include <AK/OwnPtr.h>
+#include <Kernel/IO.h>
#include <Kernel/Interrupts/IRQHandler.h>
#include <Kernel/Net/NetworkAdapter.h>
#include <Kernel/PCI/Access.h>
#include <Kernel/PCI/Device.h>
-#include <Kernel/IO.h>
+#include <Kernel/Random.h>
namespace Kernel {
@@ -103,6 +104,7 @@ private:
u8 m_interrupt_line { 0 };
bool m_has_eeprom { false };
bool m_use_mmio { false };
+ EntropySource m_entropy_source;
static const size_t number_of_rx_descriptors = 32;
static const size_t number_of_tx_descriptors = 8;
diff --git a/Kernel/Net/RTL8139NetworkAdapter.cpp b/Kernel/Net/RTL8139NetworkAdapter.cpp
index 4b496fcfd0..82a176e2cc 100644
--- a/Kernel/Net/RTL8139NetworkAdapter.cpp
+++ b/Kernel/Net/RTL8139NetworkAdapter.cpp
@@ -184,6 +184,8 @@ void RTL8139NetworkAdapter::handle_irq(const RegisterState&)
int status = in16(REG_ISR);
out16(REG_ISR, status);
+ m_entropy_source.add_random_event(status);
+
#ifdef RTL8139_DEBUG
klog() << "RTL8139NetworkAdapter::handle_irq status=0x" << String::format("%x", status);
#endif
diff --git a/Kernel/Net/RTL8139NetworkAdapter.h b/Kernel/Net/RTL8139NetworkAdapter.h
index 7db2f361e2..7255f722c9 100644
--- a/Kernel/Net/RTL8139NetworkAdapter.h
+++ b/Kernel/Net/RTL8139NetworkAdapter.h
@@ -27,10 +27,11 @@
#pragma once
#include <AK/OwnPtr.h>
+#include <Kernel/IO.h>
#include <Kernel/Net/NetworkAdapter.h>
#include <Kernel/PCI/Access.h>
#include <Kernel/PCI/Device.h>
-#include <Kernel/IO.h>
+#include <Kernel/Random.h>
namespace Kernel {
@@ -73,5 +74,6 @@ private:
u8 m_tx_next_buffer { 0 };
OwnPtr<Region> m_packet_buffer;
bool m_link_up { false };
+ EntropySource m_entropy_source;
};
}
diff --git a/Kernel/Random.cpp b/Kernel/Random.cpp
index 0b95698a90..93a84b7227 100644
--- a/Kernel/Random.cpp
+++ b/Kernel/Random.cpp
@@ -28,6 +28,7 @@
#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Devices/RandomDevice.h>
#include <Kernel/Random.h>
+#include <Kernel/Time/TimeManagement.h>
namespace Kernel {
@@ -44,7 +45,7 @@ KernelRng& KernelRng::the()
KernelRng::KernelRng()
{
if (g_cpu_supports_rdrand) {
- for (size_t i = 0; i < KernelRng::pool_count * KernelRng::reseed_threshold; ++i) {
+ for (size_t i = 0; i < resource().pool_count * resource().reseed_threshold; ++i) {
u32 value = 0;
asm volatile(
"1:\n"
@@ -52,14 +53,22 @@ KernelRng::KernelRng()
"jnc 1b\n"
: "=r"(value));
- this->add_random_event(value, i % 32);
+ this->resource().add_random_event(value, i % 32);
}
}
}
+size_t EntropySource::next_source { 0 };
+
void get_good_random_bytes(u8* buffer, size_t buffer_size)
{
- KernelRng::the().get_random_bytes(buffer, buffer_size);
+ // FIXME: What if interrupts are disabled because we're in an interrupt?
+ if (are_interrupts_enabled()) {
+ LOCKER(KernelRng::the().lock());
+ KernelRng::the().resource().get_random_bytes(buffer, buffer_size);
+ } else {
+ KernelRng::the().resource().get_random_bytes(buffer, buffer_size);
+ }
}
void get_fast_random_bytes(u8* buffer, size_t buffer_size)
diff --git a/Kernel/Random.h b/Kernel/Random.h
index f56e1ccb80..2804731740 100644
--- a/Kernel/Random.h
+++ b/Kernel/Random.h
@@ -30,6 +30,8 @@
#include <AK/Assertions.h>
#include <AK/ByteBuffer.h>
#include <AK/Types.h>
+#include <Kernel/Arch/i386/CPU.h>
+#include <Kernel/Lock.h>
#include <Kernel/StdLib.h>
#include <LibCrypto/Cipher/AES.h>
#include <LibCrypto/Cipher/Cipher.h>
@@ -110,7 +112,7 @@ private:
HashType m_pools[pool_count];
};
-class KernelRng : public FortunaPRNG<Crypto::Cipher::AESCipher, Crypto::Hash::SHA256, 256> {
+class KernelRng : public Lockable<FortunaPRNG<Crypto::Cipher::AESCipher, Crypto::Hash::SHA256, 256>> {
AK_MAKE_ETERNAL;
public:
@@ -120,6 +122,36 @@ private:
KernelRng();
};
+class EntropySource {
+ template<typename T>
+ struct Event {
+ u64 timestamp;
+ size_t source;
+ T event_data;
+ };
+
+public:
+ EntropySource()
+ : m_source(next_source++)
+ {
+ }
+
+ template<typename T>
+ void add_random_event(const T& event_data)
+ {
+ // We don't lock this because on the off chance a pool is corrupted, entropy isn't lost.
+ Event<T> event = { read_tsc(), m_source, event_data };
+ KernelRng::the().resource().add_random_event(event, m_pool);
+ m_pool++;
+ }
+
+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.
// We don't make any guarantees about actual fastness or goodness yet.