1-- The system's random bytes, fit for keys.
2
3import platform/libc
4import platform/linux
5
6--- Fill as much of `into` as the system gives at once with random bytes
7--- from its own source, which is fit for keys: how many, or the errno. On
8--- Linux it is `getrandom`, which waits while the kernel's pool is not yet
9--- ready, only early in boot, may fill a request over 256 bytes short and
10--- fails `eintr` when a signal came before any byte. On Darwin and
11--- FreeBSD it is the C library's `arc4random_buf`, which fills all of
12--- `into` and never fails.
13public link(symbol: "_landin_posix_random_bytes") random_bytes:
14 (into: []mut u8) -> (count: usize) ! errno =
15 count = 0
16 return when lenof into == 0
17 count = try system_random_bytes(into)
18end random_bytes
19
20-- The system's own calls beneath the facility above: Linux's system
21-- calls through platform/linux, and the C library through
22-- platform/libc on Darwin and FreeBSD, whose system interface it is.
23
24fixed if compiler.os == linux then
25 system_random_bytes: (into: []mut u8) -> (count: usize) ! errno =
26 result: isize = linux.getrandom(addr into[0], lenof into, 0)
27 fail errno_of(i32(-result)) when result < 0
28 fail unlisted when usize(result) > lenof into
29 count = usize(result)
30 end system_random_bytes
31elsif compiler.os == darwin or compiler.os == freebsd then
32 system_random_bytes: (into: []mut u8) -> (count: usize) ! errno =
33 libc.arc4random_buf(addr into[0], lenof into)
34 count = lenof into
35 end system_random_bytes
36end if