v2 / vlib / crypto / rand / rand_linux.c.v
40 lines · 35 sloc · 1.16 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module rand
5
6#include <sys/syscall.h>
7
8pub const C.SYS_getrandom int
9
10const read_batch_size = 256
11
12// read returns an array of `bytes_needed` random bytes read from the OS.
13pub fn read(bytes_needed int) ![]u8 {
14 mut buffer := unsafe { vcalloc_noscan(bytes_needed) }
15 mut bytes_read := 0
16 mut remaining_bytes := bytes_needed
17 // getrandom syscall wont block if requesting <= 256 bytes
18 for bytes_read < bytes_needed {
19 batch_size := if remaining_bytes > read_batch_size {
20 read_batch_size
21 } else {
22 remaining_bytes
23 }
24 rbytes := unsafe { getrandom(batch_size, buffer + bytes_read) }
25 if rbytes == -1 {
26 unsafe { free(buffer) }
27 return &ReadError{}
28 }
29 bytes_read += rbytes
30 remaining_bytes -= rbytes
31 }
32 return unsafe { buffer.vbytes(bytes_needed) }
33}
34
35fn getrandom(bytes_needed int, buffer voidptr) int {
36 if bytes_needed > read_batch_size {
37 panic('getrandom() dont request more than ${read_batch_size} bytes at once.')
38 }
39 return unsafe { C.syscall(C.SYS_getrandom, buffer, bytes_needed, 0) }
40}
41