|
|
@@ -13,14 +13,16 @@
|
|
|
|
|
|
#include "ssp_config.h"
|
|
|
#include "bh_platform.h"
|
|
|
+#include "libc_errno.h"
|
|
|
#include "random.h"
|
|
|
|
|
|
#if CONFIG_HAS_ARC4RANDOM_BUF
|
|
|
|
|
|
-void
|
|
|
+__wasi_errno_t
|
|
|
random_buf(void *buf, size_t len)
|
|
|
{
|
|
|
arc4random_buf(buf, len);
|
|
|
+ return __WASI_ESUCCESS;
|
|
|
}
|
|
|
|
|
|
#elif CONFIG_HAS_GETRANDOM
|
|
|
@@ -29,7 +31,7 @@ random_buf(void *buf, size_t len)
|
|
|
#include <sys/random.h>
|
|
|
#endif
|
|
|
|
|
|
-void
|
|
|
+__wasi_errno_t
|
|
|
random_buf(void *buf, size_t len)
|
|
|
{
|
|
|
for (;;) {
|
|
|
@@ -37,57 +39,71 @@ random_buf(void *buf, size_t len)
|
|
|
if (x < 0) {
|
|
|
if (errno == EINTR)
|
|
|
continue;
|
|
|
- os_printf("getrandom failed: %s", strerror(errno));
|
|
|
- abort();
|
|
|
+ return convert_errno(errno);
|
|
|
}
|
|
|
if ((size_t)x == len)
|
|
|
- return;
|
|
|
+ break;
|
|
|
buf = (void *)((unsigned char *)buf + x);
|
|
|
len -= (size_t)x;
|
|
|
}
|
|
|
+ return __WASI_ESUCCESS;
|
|
|
}
|
|
|
|
|
|
#elif defined(BH_PLATFORM_WINDOWS)
|
|
|
|
|
|
-#include <wincrypt.h>
|
|
|
+#include <bcrypt.h>
|
|
|
+#pragma comment(lib, "Bcrypt.lib")
|
|
|
|
|
|
-void
|
|
|
+__wasi_errno_t
|
|
|
random_buf(void *buf, size_t len)
|
|
|
{
|
|
|
- static int crypt_initialized = 0;
|
|
|
- static HCRYPTPROV provider;
|
|
|
- if (!crypt_initialized) {
|
|
|
- CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
|
|
|
- CRYPT_VERIFYCONTEXT);
|
|
|
- crypt_initialized = 1;
|
|
|
- }
|
|
|
- CryptGenRandom(provider, len, buf);
|
|
|
+ NTSTATUS ret =
|
|
|
+ BCryptGenRandom(NULL, buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
|
|
|
+
|
|
|
+ // Since we pass NULL for the algorithm handle, the only way BCryptGenRandom
|
|
|
+ // can fail is if one of the parameters is invalid
|
|
|
+ // (STATUS_INVALID_PARAMETER).
|
|
|
+ return ret ? __WASI_EINVAL : __WASI_ESUCCESS;
|
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
|
|
-static int urandom;
|
|
|
+static int urandom = -1;
|
|
|
+static __wasi_errno_t urandom_error = __WASI_ESUCCESS;
|
|
|
|
|
|
static void
|
|
|
open_urandom(void)
|
|
|
{
|
|
|
urandom = open("/dev/urandom", O_RDONLY);
|
|
|
- if (urandom < 0) {
|
|
|
- os_printf("Failed to open /dev/urandom\n");
|
|
|
- abort();
|
|
|
- }
|
|
|
+ if (urandom < 0)
|
|
|
+ urandom_error = convert_errno(errno);
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
+__wasi_errno_t
|
|
|
random_buf(void *buf, size_t len)
|
|
|
{
|
|
|
static pthread_once_t open_once = PTHREAD_ONCE_INIT;
|
|
|
- pthread_once(&open_once, open_urandom);
|
|
|
+ int pthread_ret = pthread_once(&open_once, open_urandom);
|
|
|
+
|
|
|
+ if (pthread_ret != 0)
|
|
|
+ return convert_errno(pthread_ret);
|
|
|
+
|
|
|
+ if (urandom < 0)
|
|
|
+ return urandom_error;
|
|
|
+
|
|
|
+ size_t bytes_read = 0;
|
|
|
|
|
|
- if ((size_t)read(urandom, buf, len) != len) {
|
|
|
- os_printf("Short read on /dev/urandom\n");
|
|
|
- abort();
|
|
|
+ while (bytes_read < len) {
|
|
|
+ ssize_t bytes_read_now =
|
|
|
+ read(urandom, buf + bytes_read, len - bytes_read);
|
|
|
+
|
|
|
+ if (bytes_read_now < 0)
|
|
|
+ return convert_errno(errno);
|
|
|
+
|
|
|
+ bytes_read += (size_t)bytes_read_now;
|
|
|
}
|
|
|
+
|
|
|
+ return __WASI_ESUCCESS;
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
@@ -99,8 +115,8 @@ random_buf(void *buf, size_t len)
|
|
|
// arc4random() until it lies within the range [2^k % upper, 2^k). As
|
|
|
// this range has length k * upper, we can safely obtain a number
|
|
|
// without any modulo bias.
|
|
|
-uintmax_t
|
|
|
-random_uniform(uintmax_t upper)
|
|
|
+__wasi_errno_t
|
|
|
+random_uniform(uintmax_t upper, uintmax_t *out)
|
|
|
{
|
|
|
// Compute 2^k % upper
|
|
|
// == (2^k - upper) % upper
|
|
|
@@ -108,8 +124,14 @@ random_uniform(uintmax_t upper)
|
|
|
uintmax_t lower = -upper % upper;
|
|
|
for (;;) {
|
|
|
uintmax_t value;
|
|
|
- random_buf(&value, sizeof(value));
|
|
|
- if (value >= lower)
|
|
|
- return value % upper;
|
|
|
+ __wasi_errno_t error = random_buf(&value, sizeof(value));
|
|
|
+
|
|
|
+ if (error != __WASI_ESUCCESS)
|
|
|
+ return error;
|
|
|
+
|
|
|
+ if (value >= lower) {
|
|
|
+ *out = value % upper;
|
|
|
+ return error;
|
|
|
+ }
|
|
|
}
|
|
|
}
|