From ecf8fe5d4608829273e575c2ff9e82a57500a77c Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 9 Jan 2020 15:28:02 +0200 Subject: [PATCH] Add basic urandom device --- etc/make/conf.mk | 3 ++- include/sys/random.h | 5 +++++ sys/amd64/kernel.c | 14 ++++++++++++++ sys/random.c | 25 +++++++++++++++++++++++++ sys/vfs/pseudo.c | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 include/sys/random.h create mode 100644 sys/random.c diff --git a/etc/make/conf.mk b/etc/make/conf.mk index e65e69c..7877011 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -69,7 +69,8 @@ OBJS+=$(O)/sys/debug.o \ $(O)/sys/net/netdev.o \ $(O)/sys/vfs/pseudo.o \ $(O)/sys/vfs/pty.o \ - $(O)/sys/reboot.o + $(O)/sys/reboot.o \ + $(O)/sys/random.o ifeq ($(VESA_ENABLE),1) OBJS+=$(O)/sys/psf.o \ diff --git a/include/sys/random.h b/include/sys/random.h new file mode 100644 index 0000000..5c0cd4d --- /dev/null +++ b/include/sys/random.h @@ -0,0 +1,5 @@ +#pragma once +#include "sys/types.h" + +void random_init(uint64_t seed); +uint64_t random_single(void); diff --git a/sys/amd64/kernel.c b/sys/amd64/kernel.c index e6433d8..5ea9f40 100644 --- a/sys/amd64/kernel.c +++ b/sys/amd64/kernel.c @@ -14,6 +14,8 @@ #include "sys/amd64/hw/ps2.h" #include "sys/amd64/hw/rtc.h" #include "sys/amd64/hw/con.h" +#include "sys/random.h" +#include "sys/time.h" #include "sys/panic.h" #include "sys/assert.h" #include "sys/fs/vfs.h" @@ -24,6 +26,15 @@ static multiboot_info_t *multiboot_info; +static void amd64_make_random_seed(void) { + struct rtc_time t; + rtc_read(&t); + + uint64_t s = 137831; + s += t.second + t.minute * 60 + t.hour * 3600 + t.day * 86400; + random_init(s + system_time); +} + void kernel_main(struct amd64_loader_data *data) { // Reinitialize RS232 properly ps2_init(); @@ -56,6 +67,9 @@ void kernel_main(struct amd64_loader_data *data) { tarfs_init(); } + // Initial random seed + amd64_make_random_seed(); + #if defined(AMD64_SMP) amd64_smp_init(); #endif diff --git a/sys/random.c b/sys/random.c new file mode 100644 index 0000000..43a7abe --- /dev/null +++ b/sys/random.c @@ -0,0 +1,25 @@ +#include "sys/random.h" +#include "sys/panic.h" +#include "sys/debug.h" + +static int random_ready = 0; +static uint64_t xs64_state; + +void random_init(uint64_t s) { + if (random_ready) { + kinfo("Random is ready already\n"); + } + random_ready = 1; + xs64_state = s; +} + +uint64_t random_single(void) { + if (!random_ready) { + panic("Random was not ready\n"); + } + uint64_t x = xs64_state; + x ^= x << 13; + x ^= x >> 7; + x ^= x << 17; + return xs64_state = x; +} diff --git a/sys/vfs/pseudo.c b/sys/vfs/pseudo.c index 5d9189c..76fabd8 100644 --- a/sys/vfs/pseudo.c +++ b/sys/vfs/pseudo.c @@ -1,15 +1,31 @@ #include "sys/string.h" +#include "sys/random.h" #include "sys/panic.h" +#include "sys/errno.h" #include "sys/attr.h" #include "sys/blk.h" #include "sys/dev.h" #define DEV_ZERO 0 #define DEV_NULL 1 +#define DEV_URANDOM 2 static ssize_t pseudo_write(struct blkdev *dev, const void *buf, size_t pos, size_t lim); static ssize_t pseudo_read(struct blkdev *dev, void *buf, size_t pos, size_t lim); +static void urandom_fill(void *buf, size_t lim) { + uint64_t val; + size_t i = 0; + + while (i < lim) { + val = random_single(); + + memcpy(buf + i, &val, MIN(lim - i, 8)); + + i += 8; + } +} + static struct blkdev _dev_null = { .dev_data = (void *) DEV_NULL, .write = pseudo_write, @@ -32,12 +48,25 @@ static struct dev_entry _ent_zero = { .dev_subclass = DEV_BLOCK_PSEUDO, .dev_name = "zero" }; +static struct blkdev _dev_urandom = { + .dev_data = (void *) DEV_URANDOM, + .write = pseudo_write, + .read = pseudo_read +}; +static struct dev_entry _ent_urandom = { + .dev = &_dev_urandom, + .dev_class = DEV_CLASS_BLOCK, + .dev_subclass = DEV_BLOCK_PSEUDO, + .dev_name = "urandom" +}; static ssize_t pseudo_write(struct blkdev *dev, const void *buf, size_t pos, size_t lim) { switch ((uint64_t) dev->dev_data) { case DEV_NULL: case DEV_ZERO: return lim; + case DEV_URANDOM: + return -EINVAL; default: panic("Unexpected dev id: %p\n", dev->dev_data); } @@ -50,6 +79,9 @@ static ssize_t pseudo_read(struct blkdev *dev, void *buf, size_t pos, size_t lim return lim; case DEV_NULL: return 0; + case DEV_URANDOM: + urandom_fill(buf, lim); + return lim; default: panic("Unexpected dev id: %p\n", dev->dev_data); } @@ -58,4 +90,5 @@ static ssize_t pseudo_read(struct blkdev *dev, void *buf, size_t pos, size_t lim static __init void pseudo_init(void) { dev_entry_add(&_ent_null); dev_entry_add(&_ent_zero); + dev_entry_add(&_ent_urandom); }