summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-07-04 18:29:17 +0200
committerAnton Kling <anton@kling.gg>2024-07-04 18:42:47 +0200
commit7d7f0aa9595bedf50083fb89dae049c1f064ca98 (patch)
tree9f821cb85e6deaf54b8c5b481325c7d9b231d907
parentf7752e37ce29b903e15d2579d25d4ebbaad023e6 (diff)
Random: Improve random seeding.
Now it appears to be sufficiently good at producing a distinct seed at each boot without using a /etc/seed file. Previously it did not do this. Of course this is nowhere near cryptographically secure but randomness does assist with things such as kmalloc.
-rw-r--r--kernel/drivers/pit.c4
-rw-r--r--kernel/init/kernel.c7
-rw-r--r--kernel/random.c65
-rw-r--r--kernel/random.h4
-rw-r--r--kernel/timer.c3
5 files changed, 61 insertions, 22 deletions
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
index 70dc0f9..b8a8aac 100644
--- a/kernel/drivers/pit.c
+++ b/kernel/drivers/pit.c
@@ -1,5 +1,6 @@
#include "pit.h"
#include <arch/i386/tsc.h>
+#include <random.h>
#define PIT_IO_CHANNEL_0 0x40
#define PIT_IO_MODE_COMMAND 0x43
@@ -46,7 +47,8 @@ u64 last_tsc = 0;
extern int is_switching_tasks;
void int_clock(reg_t *regs) {
-
+ u64 current_tsc = tsc_get();
+ random_add_entropy_fast((u8 *)&current_tsc, sizeof(current_tsc));
switch_counter++;
if (clock_num_ms_ticks - last_flush > 50) {
tcp_flush_acks();
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 6e5c9b4..4c7ed89 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -60,6 +60,7 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
klog(LOG_SUCCESS, "Paging Initalized");
mb = mmu_map_frames((multiboot_info_t *)addr, sizeof(multiboot_info_t));
assert(mb);
+ assert(display_driver_init(mb));
gdt_init();
klog(LOG_SUCCESS, "GDT Initalized");
@@ -67,6 +68,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
idt_init();
klog(LOG_SUCCESS, "IDT Initalized");
+ setup_random();
+
timer_start_init();
syscalls_init();
@@ -107,8 +110,6 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
shm_init();
- setup_random();
-
add_keyboard();
add_mouse();
@@ -121,8 +122,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
setup_network(gateway, bitmask);
gen_ipv4(&ip_address, 10, 0, 2, 15);
+ enable_interrupts();
- assert(display_driver_init(mb));
add_vbe_device();
int pid;
if (0 == (pid = fork())) {
diff --git a/kernel/random.c b/kernel/random.c
index 7c868ed..3ac36f2 100644
--- a/kernel/random.c
+++ b/kernel/random.c
@@ -104,9 +104,25 @@ void add_hash_pool(void) {
memcpy(internal_chacha_block + KEY, new_chacha_key, KEY_SIZE);
mix_chacha();
+
+ u64 seed[4];
+ get_random((u8 *)seed, sizeof(seed));
+ seed_xoshiro_256_pp(seed);
}
-void add_entropy(u8 *buffer, size_t size) {
+u64 entropy_fast_state = 0;
+
+static inline uint64_t xorshift64(void) {
+ uint64_t x = entropy_fast_state;
+ x ^= x << 13;
+ x ^= x >> 7;
+ x ^= x << 17;
+ return entropy_fast_state = x;
+}
+
+void random_add_entropy(u8 *buffer, u64 size) {
+ SHA1_Update(&hash_pool, &entropy_fast_state, sizeof(entropy_fast_state));
+ xorshift64();
SHA1_Update(&hash_pool, buffer, size);
hash_pool_size += size;
if (hash_pool_size >= HASH_LEN * 2) {
@@ -114,13 +130,42 @@ void add_entropy(u8 *buffer, size_t size) {
}
}
+void random_add_entropy_fast(u8 *buffer, u64 size) {
+ for (u64 i = 0; i < size; i++) {
+ entropy_fast_state ^= (buffer[i] << (8 * (i % 8)));
+ if (0 == i % 8) {
+ xorshift64();
+ }
+ }
+ xorshift64();
+}
+
void setup_random(void) {
SHA1_Init(&hash_pool);
+ return;
+}
+int random_write(BYTEPTR buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ (void)offset;
+ (void)fd;
+ random_add_entropy(buffer, len);
+ return len; // random_add_entropy() never fails to recieve (len) amount of
+ // data.
+}
+
+int random_read(BYTEPTR buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ (void)offset;
+ (void)fd;
+ get_random(buffer, len);
+ return len; // get_random() never fails to give "len" amount of data.
+}
+
+void add_random_devices(void) {
BYTE seed[1024];
int rand_fd = vfs_open("/etc/seed", O_RDWR, 0);
if (0 > rand_fd) {
klog(LOG_WARN, "/etc/seed not found");
+ add_hash_pool();
return;
}
@@ -130,7 +175,7 @@ void setup_random(void) {
klog(LOG_WARN, "/etc/seed read error");
break;
}
- add_entropy(seed, rc);
+ random_add_entropy(seed, rc);
}
add_hash_pool();
@@ -139,23 +184,7 @@ void setup_random(void) {
get_random(seed, 1024);
vfs_pwrite(rand_fd, seed, 1024, 0);
vfs_close(rand_fd);
-}
-
-int random_write(BYTEPTR buffer, u64 offset, u64 len, vfs_fd_t *fd) {
- (void)offset;
- (void)fd;
- add_entropy(buffer, len);
- return len; // add_entropy() never fails to recieve (len) amount of data.
-}
-int random_read(BYTEPTR buffer, u64 offset, u64 len, vfs_fd_t *fd) {
- (void)offset;
- (void)fd;
- get_random(buffer, len);
- return len; // get_random() never fails to give "len" amount of data.
-}
-
-void add_random_devices(void) {
devfs_add_file("/random", random_read, random_write, NULL, always_has_data,
always_can_write, FS_TYPE_CHAR_DEVICE);
devfs_add_file("/urandom", random_read, random_write, NULL, always_has_data,
diff --git a/kernel/random.h b/kernel/random.h
index 9a44bb3..533209e 100644
--- a/kernel/random.h
+++ b/kernel/random.h
@@ -6,3 +6,7 @@ void setup_random(void);
void add_random_devices(void);
void get_random(u8 *buffer, u64 len);
void get_fast_insecure_random(u8 *buffer, u64 len);
+void random_add_entropy(u8 *buffer, u64 size);
+// A interface that is not as expensive to run in comparison to
+// random_add_entropy which may take longer.
+void random_add_entropy_fast(u8 *buffer, u64 size);
diff --git a/kernel/timer.c b/kernel/timer.c
index d0ef113..2121462 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -3,6 +3,7 @@
#include <fs/devfs.h>
#include <interrupts.h>
#include <math.h>
+#include <random.h>
#include <time.h>
#include <timer.h>
#include <typedefs.h>
@@ -14,6 +15,7 @@ u64 start_tsc_time;
void timer_start_init(void) {
tsc_init();
start_tsc_time = tsc_get();
+ random_add_entropy((u8 *)&start_tsc_time, sizeof(start_tsc_time));
enable_interrupts();
cmos_init();
cmos_start_call(1, &has_unix_time, &start_unix_time);
@@ -26,6 +28,7 @@ void timer_wait_for_init(void) {
;
}
+u64 timer_current_uptime = 0; // This gets updated by the PIT handler
u64 timer_get_uptime(void) {
return tsc_calculate_ms(tsc_get());
}