From dc4ec8638c1b1dcf493c296b56b39afabe90098b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 15 Jun 2024 14:45:57 +0100 Subject: [PATCH] Add `runtime.Random_Generator` interface --- base/runtime/core.odin | 19 +++++++++++++++++++ core/crypto/crypto.odin | 20 ++++++++++++++++++++ core/math/rand/rand.odin | 27 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/base/runtime/core.odin b/base/runtime/core.odin index 8671920f5..9669e86aa 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -397,11 +397,30 @@ Logger :: struct { options: Logger_Options, } + +Random_Generator_Mode :: enum { + Read, + Query_Info, +} + +Random_Generator_Query_Info_Flag :: enum u32 { + Cryptographic, + Uniform, + External_Entropy, +} +Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32] + +Random_Generator :: struct { + procedure: proc(data: rawptr, mode: Random_Generator_Mode, p: []byte), + data: rawptr, +} + Context :: struct { allocator: Allocator, temp_allocator: Allocator, assertion_failure_proc: Assertion_Failure_Proc, logger: Logger, + random_generator: Random_Generator, user_ptr: rawptr, user_index: int, diff --git a/core/crypto/crypto.odin b/core/crypto/crypto.odin index f0874cc6d..99835e66f 100644 --- a/core/crypto/crypto.odin +++ b/core/crypto/crypto.odin @@ -4,6 +4,7 @@ helper routines. */ package crypto +import "base:runtime" import "core:mem" // compare_constant_time returns 1 iff a and b are equal, 0 otherwise. @@ -58,3 +59,22 @@ rand_bytes :: proc (dst: []byte) { _rand_bytes(dst) } + + +to_random_generator :: proc() -> runtime.Random_Generator { + return { + procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) { + switch mode { + case .Read: + rand_bytes(p) + case .Query_Info: + if len(p) != size_of(runtime.Random_Generator_Query_Info) { + return + } + info := (^runtime.Random_Generator_Query_Info)(raw_data(p)) + info^ += {.Uniform, .Cryptographic, .External_Entropy} + } + }, + data = nil, + } +} \ No newline at end of file diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 664d6abc9..552af6b8d 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -5,6 +5,7 @@ Package core:math/rand implements various random number generators package rand import "base:intrinsics" +import "base:runtime" import "core:crypto" import "core:math" import "core:mem" @@ -15,6 +16,28 @@ Rand :: struct { is_system: bool, } +to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator { + return { + procedure = proc(data: rawptr, mode: runtime.Random_Generator_Mode, p: []byte) { + r := (^Rand)(data) + switch mode { + case .Read: + _ = read(p, r) + case .Query_Info: + if len(p) != size_of(runtime.Random_Generator_Query_Info) { + return + } + info := (^runtime.Random_Generator_Query_Info)(raw_data(p)) + info^ += {.Uniform} + if r.is_system { + info^ += {.External_Entropy} + } + } + }, + data = r, + } +} + @(private) global_rand := create(u64(intrinsics.read_cycle_counter())) @@ -150,6 +173,10 @@ _random_u64 :: proc(r: ^Rand) -> u64 { r := r switch { case r == nil: + if res: u64; runtime.random_generator_read_ptr(context.random_generator, &res, size_of(res)) { + return res + } + r = &global_rand case r.is_system: value: u64