changed: using cryptographic random number generation
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 14 May 2023 21:50:54 +0000 (16:50 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 14 May 2023 21:50:54 +0000 (16:50 -0500)
CHANGELOG
core/random/random.onyx
core/runtime/platform/onyx/platform.onyx
core/runtime/platform/wasi/platform.onyx
runtime/onyx_runtime.c
runtime/src/ort_os.h
shared/include/onyx_library.h
shared/include/small_windows.h

index 94cb8316a7149f59769adf81480c7af9738f9dab..6e9c5f2197baf52d75f8ecb41f69159f46c28866 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,6 +22,9 @@ Changes:
 * API for time remains the same, but reduced dependencies on external time things,
     like strftime, localtime and mktime.
 * Ergnomic improvements to `onyx pkg`.
+* Not relying on time for random number seeding, if cryptographic random number generation is possible.
+    - Using `getrandom` on Linux, and `BcryptGenRandom` on Windows.
+    - Using `random_get` on WASI.
 
 Bugfixes:
 * Fixed missing `use core` in `optional.onyx`.
index 400df811b5db7e80312035ca021661996c870fdd..c8bbe7d3308ae9a0a67c716c16c49ce7d4cceeb1 100644 (file)
@@ -1,6 +1,7 @@
 package core.random
 
 use core
+use runtime
 
 #doc "The state of a random number generator."
 Random :: struct {
@@ -116,10 +117,18 @@ string :: (bytes_long: u32, alpha_numeric := false, allocator := context.allocat
     RANDOM_MULTIPLIER :: 25214903917
     RANDOM_INCREMENT  :: cast(i64) 11
 
-    #if #defined(core.os.time) {
-        __initial_value :: #(core.os.time())
+    #if #defined(runtime.platform.__random_get) {
+        __initial_value :: #(do {
+            v: u64;
+            runtime.platform.__random_get(.{ ~~&v, sizeof typeof v });
+            return v;
+        })
     } else {
-        __initial_value :: #(8675309)
+        #if #defined(core.os.time) {
+            __initial_value :: #(core.os.time())
+        } else {
+            __initial_value :: #(8675309)
+        }
     }
 }
 
index 5936fcc478828f3eeaa5122dc1bccf27f4fd2f69..5827d082725e0565af775a5438d8c7531da91104 100644 (file)
@@ -76,6 +76,7 @@ ProcessData :: #distinct u64
 
     // Misc
     __file_get_standard :: (fd: i32, out: &FileData) -> bool ---
+    __random_get        :: (buf: [] u8) -> void ---
 }
 
 __start :: () {
index 9082bcf4a0fafde018baace95cd9d78f148688f9..e11ddbe2295f1ba72b768e76ceeff56b2fd5007a 100644 (file)
@@ -14,7 +14,8 @@ use wasi {
     poll_oneoff, fd_write, fd_datasync, fd_read,
     args_get, args_sizes_get,
     proc_exit,
-    clock_time_get, Timestamp
+    clock_time_get, Timestamp,
+    random_get,
 }
 use runtime {
     __runtime_initialize,
@@ -91,6 +92,10 @@ __time :: () -> i64 {
     return time / 1000000;
 }
 
+__random_get :: (buf: [] u8) {
+    random_get(buf.data, buf.length);
+}
+
 
 // Sets up everything needed for execution.
 __start :: () {
index a85e9f6aac4c5140647b5ad4ad5cd087184fb943..7f4b023d241ed9c2b3883f8a737cad8109e25482 100644 (file)
@@ -70,6 +70,7 @@ ONYX_LIBRARY {
     ONYX_FUNC(__sleep)
     ONYX_FUNC(__time)
     ONYX_FUNC(__lookup_env)
+    ONYX_FUNC(__random_get)
     ONYX_FUNC(__register_cleanup)
 
     ONYX_FUNC(__net_create_socket)
index bfc7c3ca4158d24c9aee72d7d774327de33f6c05..af5292cd21f8a3ed810e94f93f27fd8d643a014f 100644 (file)
@@ -84,6 +84,20 @@ ONYX_DEF(__lookup_env, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
 }
 
 
+ONYX_DEF(__random_get, (WASM_PTR, WASM_I32), ()) {
+    #ifdef _BH_LINUX
+    getrandom(ONYX_PTR(params->data[0].of.i32), params->data[1].of.i32, 0);
+    #endif
+
+    #ifdef _BH_WINDOWS
+    BCRYPT_ALG_HANDLE alg;
+    BCryptOpenAlgorithmProvider(&alg, L"SHA256", NULL, 0);
+    BCryptGenRandom(alg, ONYX_PTR(params->data[0].of.i32), params->data[1].of.i32, 0);
+    BCryptCloseAlgorithmProvider(alg, 0);
+    #endif
+
+    return NULL;
+}
 
 
 
index 573de3040ed5f893642b27e0529a68ade9dd4625..feb859ddf494642d17a2ebbd183c231053d9a879 100644 (file)
@@ -84,6 +84,8 @@ typedef struct WasmFuncDefinition {
     } \
     struct WasmFuncDefinition *ONYX_MODULE_NAME_GEN(ONYX_LIBRARY_NAME)[] =
 
+#define WASM_PTR WASM_I32
+
 // Shorter names
 #ifndef ONYX_NO_SHORT_NAMES
 #undef  BOOL
@@ -96,7 +98,7 @@ typedef struct WasmFuncDefinition {
 #define LONG WASM_I64
 #define FLOAT WASM_F32
 #define DOUBLE WASM_F64
-#define PTR WASM_I32
+#define PTR WASM_PTR
 #endif
 
 #define ONYX_PTR(p) ((void*) (p != 0 ? (runtime->wasm_memory_data(runtime->wasm_memory) + p) : NULL))
index 28cea0bd0155711b0462e80a4b9501ab3ef9911c..93cc4bba74decd5ed22192c25081a062665292b9 100644 (file)
@@ -53,6 +53,7 @@ typedef HANDLE HGLOBAL;
 typedef HANDLE HLOCAL;
 typedef HANDLE GLOBALHANDLE;
 typedef HANDLE LOCALHANDLE;
+typedef HANDLE BCRYPT_ALG_HANDLE;
 typedef void *HGDIOBJ;
 
 #define DECLARE_HANDLE(name) typedef HANDLE name
@@ -442,3 +443,23 @@ GB_DLL_IMPORT short WINAPI htons(short hostshort);
 GB_DLL_IMPORT int   WINAPI htonl(int   hostint);
 GB_DLL_IMPORT short WINAPI ntohs(short netshort);
 GB_DLL_IMPORT int   WINAPI ntohl(int   netint);
+
+
+GB_DLL_IMPORT NTSTATUS BCryptGenRandom(
+    BCRYPT_ALG_HANDLE hAlgorithm,
+    unsigned char *   pbBuffer,
+    unsigned long     cbBuffer,
+    unsigned long     wFlags
+);
+
+GB_DLL_IMPORT NTSTATUS BCryptOpenAlgorithmProvider(
+    BCRYPT_ALG_HANDLE *phAlgorithm,
+    const wchar_t *    pszAlgId,
+    const wchar_t *    pszImplementation,
+    unsigned long      dwFlags
+);
+
+GB_DLL_IMPORT NTSTATUS BCryptCloseAlgorithmProvider(
+    BCRYPT_ALG_HANDLE hAlgorithm,
+    unsigned long     dwFlags
+);