diff --git a/src/libraries/Native/Unix/System.Native/pal_random.c b/src/libraries/Native/Unix/System.Native/pal_random.c index 8f5e8927834a66..b824b2968f95cf 100644 --- a/src/libraries/Native/Unix/System.Native/pal_random.c +++ b/src/libraries/Native/Unix/System.Native/pal_random.c @@ -63,11 +63,24 @@ Return 0 on success, -1 on failure. */ int32_t SystemNative_GetCryptographicallySecureRandomBytes(uint8_t* buffer, int32_t bufferLength) { + assert(buffer != NULL); + +#ifdef __EMSCRIPTEN__ + extern int32_t dotnet_browser_entropy(uint8_t* buffer, int32_t bufferLength); + static bool sMissingBrowserCrypto; + if (!sMissingBrowserCrypto) + { + int32_t bff = dotnet_browser_entropy(buffer, bufferLength); + if (bff == -1) + sMissingBrowserCrypto = true; + else + return 0; + } +#else + static volatile int rand_des = -1; static bool sMissingDevURandom; - assert(buffer != NULL); - if (!sMissingDevURandom) { if (rand_des == -1) @@ -121,6 +134,6 @@ int32_t SystemNative_GetCryptographicallySecureRandomBytes(uint8_t* buffer, int3 return 0; } } - +#endif return -1; } diff --git a/src/libraries/Native/Unix/System.Native/pal_random.js b/src/libraries/Native/Unix/System.Native/pal_random.js new file mode 100644 index 00000000000000..231eda0b8ca863 --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/pal_random.js @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var DotNetEntropyLib = { + $DOTNETENTROPY: { + }, + dotnet_browser_entropy : function (buffer, bufferLength) { + // check that we have crypto available + if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') { + // for modern web browsers + // map the work array to the memory buffer passed with the length + var wrkArray = new Uint8Array(Module.HEAPU8.buffer, buffer, bufferLength); + crypto.getRandomValues(wrkArray); + return 0; + } else { + // we couldn't find a proper implementation, as Math.random() is not suitable + // instead of aborting here we will return and let managed code handle the message + return -1; + } + }, +}; + +autoAddDeps(DotNetEntropyLib, '$DOTNETENTROPY') +mergeInto(LibraryManager.library, DotNetEntropyLib) diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 4fc42d4f7ad0d3..12f1962920fd97 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -15,6 +15,7 @@ PINVOKE_TABLE?=$(TOP)/artifacts/obj/wasm/pinvoke-table.h MONO_BIN_DIR?=$(BINDIR)/mono/Browser.wasm.$(CONFIG) NATIVE_BIN_DIR?=$(BINDIR)/native/net5.0-Browser-$(CONFIG)-wasm ICU_LIBDIR?= +SYSTEM_NATIVE_LIBDIR?=$(TOP)/src/libraries/Native/Unix/System.Native ENABLE_ES6?=false all: build-native icu-data @@ -81,8 +82,8 @@ $(NATIVE_BIN_DIR): $(BUILDS_OBJ_DIR): mkdir -p $$@ -$(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js $(2) | $(NATIVE_BIN_DIR) - $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js +$(NATIVE_BIN_DIR)/dotnet.js: $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o runtime/library_mono.js runtime/binding_support.js runtime/dotnet_support.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(2) | $(NATIVE_BIN_DIR) + $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 7cf27afd16a217..1d217aae5dade3 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -62,12 +62,14 @@ if (typeof console !== "undefined") { console.error = console.log; } -if (typeof crypto == 'undefined') { +if (typeof crypto === 'undefined') { + // **NOTE** this is a simple insecure polyfill for testing purposes only // /dev/random doesn't work on js shells, so define our own // See library_fs.js:createDefaultDevices () var crypto = { getRandomValues: function (buffer) { - buffer[0] = (Math.random()*256)|0; + for (var i = 0; i < buffer.length; i++) + buffer [i] = (Math.random () * 256) | 0; } } } diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 4ae04e16048d42..dafc3e2068d8a3 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -211,7 +211,7 @@ var MonoSupportLib = { }, /** @returns {ManagedPointer} */ get: function (index) { - this._check_in_range (index); + this._check_in_range (index); return Module.HEAP32[this.get_address_32 (index)]; }, set: function (index, value) { @@ -317,7 +317,7 @@ var MonoSupportLib = { throw new Error ("capacity >= 1"); capacity = capacity | 0; - + var capacityBytes = capacity * 4; var offset = Module._malloc (capacityBytes); if ((offset % 4) !== 0) @@ -328,7 +328,7 @@ var MonoSupportLib = { var result = Object.create (this._mono_wasm_root_buffer_prototype); result.__offset = offset; result.__offset32 = (offset / 4) | 0; - result.__count = capacity; + result.__count = capacity; result.length = capacity; result.__handle = this.mono_wasm_register_root (offset, capacityBytes, msg || 0); @@ -347,7 +347,7 @@ var MonoSupportLib = { mono_wasm_new_root: function (value) { var index = this._mono_wasm_claim_scratch_index (); var buffer = this._scratch_root_buffer; - + var result = Object.create (this._mono_wasm_root_prototype); result.__buffer = buffer; result.__index = index; @@ -395,7 +395,7 @@ var MonoSupportLib = { * Multiple objects may be passed on the argument list. * 'undefined' may be passed as an argument so it is safe to call this method from finally blocks * even if you are not sure all of your roots have been created yet. - * @param {... WasmRoot} roots + * @param {... WasmRoot} roots */ mono_wasm_release_roots: function () { for (var i = 0; i < arguments.length; i++) {