aboutsummaryrefslogtreecommitdiff
path: root/lib/std/start.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-12-17 20:03:41 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-12-18 12:22:46 -0700
commit013efaf13987acfa6b41d40f07900c1ea77f5bda (patch)
tree14325d114eb66312b3545f3a897142400dfb7c16 /lib/std/start.zig
parentce65533985caa9e2da567948e36d7d4ba0185005 (diff)
downloadzig-013efaf13987acfa6b41d40f07900c1ea77f5bda.tar.gz
zig-013efaf13987acfa6b41d40f07900c1ea77f5bda.zip
std: introduce a thread-local CSPRNG for general use
std.crypto.random * cross platform, even freestanding * can't fail. on initialization for some systems requires calling os.getrandom(), in which case there are rare but theoretically possible errors. The code panics in these cases, however the application may choose to override the default seed function and then handle the failure another way. * thread-safe * supports the full Random interface * cryptographically secure * no syscall required to initialize on Linux (AT_RANDOM) * calls arc4random on systems that support it `std.crypto.randomBytes` is removed in favor of `std.crypto.random.bytes`. I moved some of the Random implementations into their own files in the interest of organization. stage2 no longer requires passing a RNG; instead it uses this API. Closes #6704
Diffstat (limited to 'lib/std/start.zig')
-rw-r--r--lib/std/start.zig26
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 7d3a9c45c7..b6fb7e4dfd 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -10,6 +10,7 @@ const std = @import("std.zig");
const builtin = std.builtin;
const assert = std.debug.assert;
const uefi = std.os.uefi;
+const tlcsprng = @import("crypto/tlcsprng.zig");
var argc_argv_ptr: [*]usize = undefined;
@@ -215,6 +216,28 @@ fn posixCallMainAndExit() noreturn {
std.os.linux.tls.initStaticTLS();
}
+ {
+ // Initialize the per-thread CSPRNG since Linux gave us the handy-dandy
+ // AT_RANDOM. This depends on the TLS initialization above.
+ var i: usize = 0;
+ while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
+ switch (auxv[i].a_type) {
+ std.elf.AT_RANDOM => {
+ // "The address of sixteen bytes containing a random value."
+ const addr = auxv[i].a_un.a_val;
+ if (addr == 0) break;
+ const ptr = @intToPtr(*const [16]u8, addr);
+ var seed: [32]u8 = undefined;
+ seed[0..16].* = ptr.*;
+ seed[16..].* = ptr.*;
+ tlcsprng.init(seed);
+ break;
+ },
+ else => continue,
+ }
+ }
+ }
+
// TODO This is disabled because what should we do when linking libc and this code
// does not execute? And also it's causing a test failure in stack traces in release modes.
@@ -250,6 +273,9 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
}
fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 {
+ // We do not attempt to initialize tlcsprng from AT_RANDOM here because
+ // libc owns the start code, not us, and therefore libc ows the random bytes
+ // from AT_RANDOM.
var env_count: usize = 0;
while (c_envp[env_count] != null) : (env_count += 1) {}
const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];