diff options
Diffstat (limited to 'v_windows/v/old/vlib/crypto/rand')
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/crypto_rand_read_test.v | 15 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/rand.v | 10 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/rand_darwin.c.v | 21 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/rand_default.c.v | 9 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/rand_linux.c.v | 39 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/rand_solaris.c.v | 42 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/rand_windows.c.v | 25 | ||||
-rw-r--r-- | v_windows/v/old/vlib/crypto/rand/utils.v | 55 |
8 files changed, 216 insertions, 0 deletions
diff --git a/v_windows/v/old/vlib/crypto/rand/crypto_rand_read_test.v b/v_windows/v/old/vlib/crypto/rand/crypto_rand_read_test.v new file mode 100644 index 0000000..824923d --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/crypto_rand_read_test.v @@ -0,0 +1,15 @@ +import crypto.rand + +fn test_reading() ? { + a := rand.read(32) ? + // dump(a.hex()) + assert a.len == 32 + mut histogram := [256]int{} + for b in a { + histogram[b]++ + } + // dump(histogram) + for h in histogram { + assert h < 10 + } +} diff --git a/v_windows/v/old/vlib/crypto/rand/rand.v b/v_windows/v/old/vlib/crypto/rand/rand.v new file mode 100644 index 0000000..0703558 --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/rand.v @@ -0,0 +1,10 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +struct ReadError { + msg string = 'crypto.rand.read() error reading random bytes' + code int +} diff --git a/v_windows/v/old/vlib/crypto/rand/rand_darwin.c.v b/v_windows/v/old/vlib/crypto/rand/rand_darwin.c.v new file mode 100644 index 0000000..a53198b --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/rand_darwin.c.v @@ -0,0 +1,21 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +#include <Security/SecRandom.h> + +#flag darwin -framework Security + +fn C.SecRandomCopyBytes(rnd C.SecRandomRef, count size_t, bytes voidptr) int + +// read returns an array of `bytes_needed` random bytes read from the OS. +pub fn read(bytes_needed int) ?[]byte { + mut buffer := []byte{len: bytes_needed} + status := C.SecRandomCopyBytes(C.SecRandomRef(0), bytes_needed, buffer.data) + if status != 0 { + return IError(&ReadError{}) + } + return buffer +} diff --git a/v_windows/v/old/vlib/crypto/rand/rand_default.c.v b/v_windows/v/old/vlib/crypto/rand/rand_default.c.v new file mode 100644 index 0000000..2e1e823 --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/rand_default.c.v @@ -0,0 +1,9 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module rand + +// read returns an array of `bytes_needed` random bytes read from the OS. +pub fn read(bytes_needed int) ?[]byte { + return error('rand.read is not implemented on this platform') +} diff --git a/v_windows/v/old/vlib/crypto/rand/rand_linux.c.v b/v_windows/v/old/vlib/crypto/rand/rand_linux.c.v new file mode 100644 index 0000000..52ff3da --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/rand_linux.c.v @@ -0,0 +1,39 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +module rand + +#include <sys/syscall.h> + +const ( + read_batch_size = 256 +) + +// read returns an array of `bytes_needed` random bytes read from the OS. +pub fn read(bytes_needed int) ?[]byte { + mut buffer := unsafe { malloc_noscan(bytes_needed) } + mut bytes_read := 0 + mut remaining_bytes := bytes_needed + // getrandom syscall wont block if requesting <= 256 bytes + for bytes_read < bytes_needed { + batch_size := if remaining_bytes > rand.read_batch_size { + rand.read_batch_size + } else { + remaining_bytes + } + rbytes := unsafe { getrandom(batch_size, buffer + bytes_read) } + if rbytes == -1 { + unsafe { free(buffer) } + return IError(&ReadError{}) + } + bytes_read += rbytes + } + return unsafe { buffer.vbytes(bytes_needed) } +} + +fn getrandom(bytes_needed int, buffer voidptr) int { + if bytes_needed > rand.read_batch_size { + panic('getrandom() dont request more than $rand.read_batch_size bytes at once.') + } + return unsafe { C.syscall(C.SYS_getrandom, buffer, bytes_needed, 0) } +} diff --git a/v_windows/v/old/vlib/crypto/rand/rand_solaris.c.v b/v_windows/v/old/vlib/crypto/rand/rand_solaris.c.v new file mode 100644 index 0000000..8d0ba0c --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/rand_solaris.c.v @@ -0,0 +1,42 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +#include <sys/random.h> + +fn C.getrandom(p &byte, n size_t, flags u32) int + +const ( + read_batch_size = 256 +) + +// read returns an array of `bytes_needed` random bytes read from the OS. +pub fn read(bytes_needed int) ?[]byte { + mut buffer := unsafe { malloc_noscan(bytes_needed) } + mut bytes_read := 0 + mut remaining_bytes := bytes_needed + // getrandom syscall wont block if requesting <= 256 bytes + for bytes_read < bytes_needed { + batch_size := if remaining_bytes > rand.read_batch_size { + rand.read_batch_size + } else { + remaining_bytes + } + rbytes := unsafe { getrandom(batch_size, buffer + bytes_read) } + if rbytes == -1 { + unsafe { free(buffer) } + return IError(&ReadError{}) + } + bytes_read += rbytes + } + return unsafe { buffer.vbytes(bytes_needed) } +} + +fn v_getrandom(bytes_needed int, buffer voidptr) int { + if bytes_needed > rand.read_batch_size { + panic('getrandom() dont request more than $rand.read_batch_size bytes at once.') + } + return C.getrandom(buffer, bytes_needed, 0) +} diff --git a/v_windows/v/old/vlib/crypto/rand/rand_windows.c.v b/v_windows/v/old/vlib/crypto/rand/rand_windows.c.v new file mode 100644 index 0000000..075a3ed --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/rand_windows.c.v @@ -0,0 +1,25 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +#flag windows -Llibraries/bcrypt +#flag windows -lbcrypt +#include <bcrypt.h> + +const ( + status_success = 0x00000000 + bcrypt_use_system_preferred_rng = 0x00000002 +) + +// read returns an array of `bytes_needed` random bytes read from the OS. +pub fn read(bytes_needed int) ?[]byte { + mut buffer := []byte{len: bytes_needed} + // use bcrypt_use_system_preferred_rng because we passed null as algo + status := C.BCryptGenRandom(0, buffer.data, bytes_needed, rand.bcrypt_use_system_preferred_rng) + if status != rand.status_success { + return IError(&ReadError{}) + } + return buffer +} diff --git a/v_windows/v/old/vlib/crypto/rand/utils.v b/v_windows/v/old/vlib/crypto/rand/utils.v new file mode 100644 index 0000000..31eaf2d --- /dev/null +++ b/v_windows/v/old/vlib/crypto/rand/utils.v @@ -0,0 +1,55 @@ +// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +module rand + +import math.bits +import encoding.binary + +// int_u64 returns a random unsigned 64-bit integer `u64` read from a real OS source of entropy. +pub fn int_u64(max u64) ?u64 { + bitlen := bits.len_64(max) + if bitlen == 0 { + return u64(0) + } + k := (bitlen + 7) / 8 + mut b := u64(bitlen % 8) + if b == u64(0) { + b = u64(8) + } + mut n := u64(0) + for { + mut bytes := read(k) ? + bytes[0] &= byte(int(u64(1) << b) - 1) + x := bytes_to_u64(bytes) + n = x[0] + // NOTE: maybe until we have bigint could do it another way? + // if x.len > 1 { + // n = u64(u32(x[1])<<u32(32)) | n + // } + if n < max { + return n + } + } + return n +} + +fn bytes_to_u64(b []byte) []u64 { + ws := 64 / 8 + mut z := []u64{len: ((b.len + ws - 1) / ws)} + mut i := b.len + for k := 0; i >= ws; k++ { + z[k] = binary.big_endian_u64(b[i - ws..i]) + i -= ws + } + if i > 0 { + mut d := u64(0) + for s := u64(0); i > 0; s += u64(8) { + d |= u64(b[i - 1]) << s + i-- + } + z[z.len - 1] = d + } + return z +} |