Просмотр исходного кода

Use next generation crypto API on Windows (#2769)

CryptGenRandom is deprecated by Microsoft and may be removed in future
releases. They recommend to use the next generation API instead. See
https://learn.microsoft.com/en-us/windows/win32/seccng/cng-portal for
more details. Also, refactor the random functions to return error codes
rather than aborting the program if they fail.
zoraaver 2 лет назад
Родитель
Сommit
b39fd516d3

+ 19 - 9
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

@@ -614,14 +614,21 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in,
 }
 
 // Picks an unused slot from the file descriptor table.
-static __wasi_fd_t
-fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock)
+static __wasi_errno_t
+fd_table_unused(struct fd_table *ft, __wasi_fd_t *out) REQUIRES_SHARED(ft->lock)
 {
     assert(ft->size > ft->used && "File descriptor table has no free slots");
     for (;;) {
-        __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size);
-        if (ft->entries[fd].object == NULL)
-            return fd;
+        uintmax_t random_fd = 0;
+        __wasi_errno_t error = random_uniform(ft->size, &random_fd);
+
+        if (error != __WASI_ESUCCESS)
+            return error;
+
+        if (ft->entries[(__wasi_fd_t)random_fd].object == NULL) {
+            *out = (__wasi_fd_t)random_fd;
+            return error;
+        }
     }
 }
 
@@ -641,10 +648,14 @@ fd_table_insert(wasm_exec_env_t exec_env, struct fd_table *ft,
         return convert_errno(errno);
     }
 
-    *out = fd_table_unused(ft);
+    __wasi_errno_t error = fd_table_unused(ft, out);
+
+    if (error != __WASI_ESUCCESS)
+        return error;
+
     fd_table_attach(ft, *out, fo, rights_base, rights_inheriting);
     rwlock_unlock(&ft->lock);
-    return 0;
+    return error;
 }
 
 // Inserts a numerical file descriptor into the file descriptor table.
@@ -2282,8 +2293,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
 __wasi_errno_t
 wasmtime_ssp_random_get(void *buf, size_t nbyte)
 {
-    random_buf(buf, nbyte);
-    return 0;
+    return random_buf(buf, nbyte);
 }
 
 __wasi_errno_t

+ 52 - 30
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c

@@ -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;
+        }
     }
 }

+ 6 - 2
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h

@@ -14,8 +14,12 @@
 #ifndef RANDOM_H
 #define RANDOM_H
 
-void
+#include "bh_platform.h"
+
+__wasi_errno_t
 random_buf(void *, size_t);
-uintmax_t random_uniform(uintmax_t);
+
+__wasi_errno_t
+random_uniform(uintmax_t upper, uintmax_t *out);
 
 #endif