diff --git a/vlib/crypto/rand/rand.v b/vlib/crypto/rand/rand.v new file mode 100644 index 0000000000..8b412d2f60 --- /dev/null +++ b/vlib/crypto/rand/rand.v @@ -0,0 +1,21 @@ +// Copyright (c) 2019 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 + +const ( + ReadError = error('crypro.rand.read() error reading random bytes.') +) + +// NOTE: temp until we have []bytes(buff) +fn c_array_to_bytes_tmp(len, buffer voidptr) []byte { + mut arr := []byte + arr = array { + len: len + cap: 1 + element_size: 1 + data: buffer + } + return arr +} diff --git a/vlib/crypto/rand/rand_lin.v b/vlib/crypto/rand/rand_lin.v new file mode 100644 index 0000000000..c5d3df6c2f --- /dev/null +++ b/vlib/crypto/rand/rand_lin.v @@ -0,0 +1,51 @@ +// Copyright (c) 2019 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 + +#include + +import const( + SYS_getrandom +) + +// const ( +// SYS_getrandom = 278 // AArch65 +// SYS_getrandom = 384 // ARM +// SYS_getrandom = 355 // x86 +// SYS_getrandom = 318 // x86_64 +// ) + +const ( + ReadBatchSize = 256 +) + +pub fn read(bytes_needed int) ?[]byte { + mut buffer := malloc(bytes_needed) + mut bytes_read := 0 + // getrandom syscall wont block if requesting <= 256 bytes + if bytes_needed > ReadBatchSize { + no_batches := int(math.floor(f64(bytes_needed/ReadBatchSize))) + for i:=0; i ReadBatchSize { + panic('_getrandom() dont request more thane $ReadBatchSize bytes at once.') + } + return C.syscall(SYS_getrandom, buffer, bytes_needed, 0) +} diff --git a/vlib/crypto/rand/rand_mac.v b/vlib/crypto/rand/rand_mac.v new file mode 100644 index 0000000000..085de05345 --- /dev/null +++ b/vlib/crypto/rand/rand_mac.v @@ -0,0 +1,26 @@ +// Copyright (c) 2019 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 darwin -framework Security + +// import const ( +// kSecRandomDefault +// errSecSuccess +// ) + +const ( + kSecRandomDefault = 0 + errSecSuccess = 0 +) + +pub fn read(bytes_needed int) ?[]byte { + mut buffer := malloc(bytes_needed) + status := C.SecRandomCopyBytes(kSecRandomDefault, bytes_needed, buffer) + if status != errSecSuccess { + return ReadError + } + return c_array_to_bytes_tmp(bytes_needed, buffer) +} diff --git a/vlib/crypto/rand/rand_test.v b/vlib/crypto/rand/rand_test.v new file mode 100644 index 0000000000..7d0bc0c97b --- /dev/null +++ b/vlib/crypto/rand/rand_test.v @@ -0,0 +1,13 @@ +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. + +import crypto.rand + +fn test_crypto_rand() { + r := rand.read(100) or { + assert false + return + } + assert r.len == 100 +} diff --git a/vlib/crypto/rand/rand_win.v b/vlib/crypto/rand/rand_win.v new file mode 100644 index 0000000000..200b98ffb7 --- /dev/null +++ b/vlib/crypto/rand/rand_win.v @@ -0,0 +1,23 @@ +// Copyright (c) 2019 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 -lbcrypt +#include + +const ( + STATUS_SUCCESS = 0x00000000 + BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002 +) + +pub fn read(bytes_needed int) ?[]byte { + mut buffer := malloc(bytes_needed) + // use BCRYPT_USE_SYSTEM_PREFERRED_RNG because we passed null as algo + status := C.BCryptGenRandom(0, buffer, bytes_needed, BCRYPT_USE_SYSTEM_PREFERRED_RNG) + if status != STATUS_SUCCESS { + return ReadError + } + return c_array_to_bytes_tmp(bytes_needed, buffer) +}