Skip to content

Commit

Permalink
[browser] refactor entropy (#93466)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara committed Oct 16, 2023
1 parent c836f5a commit ee9dd81
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@
<PlatformManifestFileEntry Include="icudt_optimal_no_CJK.dat" IsNative="true" />
<PlatformManifestFileEntry Include="icudt_hybrid.dat" IsNative="true" />
<PlatformManifestFileEntry Include="package.json" IsNative="true" />
<PlatformManifestFileEntry Include="pal_random.lib.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.es6.pre.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.es6.lib.js" IsNative="true" />
<PlatformManifestFileEntry Include="dotnet.es6.extpost.js" IsNative="true" />
Expand Down
3 changes: 3 additions & 0 deletions src/mono/sample/wasm/browser-advanced/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public static int Main(string[] args)
{
Console.WriteLine ("Hello, World!");

var rand = new Random();
Console.WriteLine ("Today's lucky number is " + rand.Next(100) + " and " + Guid.NewGuid());

var start = DateTime.UtcNow;
var timezonesCount = TimeZoneInfo.GetSystemTimeZones().Count;
var end = DateTime.UtcNow;
Expand Down
4 changes: 2 additions & 2 deletions src/mono/wasm/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ target_link_libraries(dotnet.native
${NATIVE_BIN_DIR}/libSystem.IO.Compression.Native.a)

set_target_properties(dotnet.native PROPERTIES
LINK_DEPENDS "${NATIVE_BIN_DIR}/src/emcc-default.rsp;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js;${NATIVE_BIN_DIR}/src/pal_random.lib.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js;"
LINK_FLAGS "@${NATIVE_BIN_DIR}/src/emcc-default.rsp @${NATIVE_BIN_DIR}/src/emcc-link.rsp ${CONFIGURATION_LINK_FLAGS} --pre-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js --js-library ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js --js-library ${NATIVE_BIN_DIR}/src/pal_random.lib.js --extern-post-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js "
LINK_DEPENDS "${NATIVE_BIN_DIR}/src/emcc-default.rsp;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js;${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js;"
LINK_FLAGS "@${NATIVE_BIN_DIR}/src/emcc-default.rsp @${NATIVE_BIN_DIR}/src/emcc-link.rsp ${CONFIGURATION_LINK_FLAGS} --pre-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.pre.js --js-library ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.lib.js --extern-post-js ${NATIVE_BIN_DIR}/src/es6/dotnet.es6.extpost.js "
RUNTIME_OUTPUT_DIRECTORY "${NATIVE_BIN_DIR}")

set(ignoreMeWasmOptFlags "${CONFIGURATION_WASM_OPT_FLAGS}")
Expand Down
33 changes: 33 additions & 0 deletions src/mono/wasm/runtime/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { isSharedArrayBuffer, localHeapViewU8 } from "./memory";

// batchedQuotaMax is the max number of bytes as specified by the api spec.
// If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm.
// https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues
const batchedQuotaMax = 65536;

export function mono_wasm_browser_entropy(bufferPtr: number, bufferLength: number): number {
if (!globalThis.crypto || !globalThis.crypto.getRandomValues) {
return -1;
}

const memoryView = localHeapViewU8();
const targetView = memoryView.subarray(bufferPtr, bufferPtr + bufferLength);

// When threading is enabled, Chrome doesn't want SharedArrayBuffer to be passed to crypto APIs
const needsCopy = isSharedArrayBuffer(memoryView.buffer);
const targetBuffer = needsCopy
? new Uint8Array(bufferLength)
: targetView;

// fill the targetBuffer in batches of batchedQuotaMax
for (let i = 0; i < bufferLength; i += batchedQuotaMax) {
const targetBatch = targetBuffer.subarray(i, i + Math.min(bufferLength - i, batchedQuotaMax));
globalThis.crypto.getRandomValues(targetBatch);
}

if (needsCopy) {
targetView.set(targetBuffer);
}

return 0;
}
4 changes: 4 additions & 0 deletions src/mono/wasm/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { mono_wasm_typed_array_to_array_ref } from "./net6-legacy/js-to-cs";
import { mono_wasm_typed_array_from_ref } from "./net6-legacy/buffers";
import { mono_wasm_get_culture_info } from "./hybrid-globalization/culture-info";
import { mono_wasm_get_first_day_of_week, mono_wasm_get_first_week_of_year } from "./hybrid-globalization/locales";
import { mono_wasm_browser_entropy } from "./crypto";

// the JS methods would be visible to EMCC linker and become imports of the WASM module

Expand Down Expand Up @@ -98,6 +99,9 @@ export const mono_wasm_imports = [
mono_wasm_set_entrypoint_breakpoint,
mono_wasm_event_pipe_early_startup_callback,

// src/native/minipal/random.c
mono_wasm_browser_entropy,

// corebindings.c
mono_wasm_release_cs_owned_object,
mono_wasm_bind_js_function,
Expand Down
5 changes: 4 additions & 1 deletion src/mono/wasm/runtime/memory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,10 @@ export function receiveWorkerHeapViews() {

const sharedArrayBufferDefined = typeof SharedArrayBuffer !== "undefined";
export function isSharedArrayBuffer(buffer: any): buffer is SharedArrayBuffer {
if (!MonoWasmThreads) return false;
// this condition should be eliminated by rollup on non-threading builds
if (!MonoWasmThreads) return false;
// BEWARE: In some cases, `instanceof SharedArrayBuffer` returns false even though buffer is an SAB.
// Patch adapted from https://github.com/emscripten-core/emscripten/pull/16994
// See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag
return sharedArrayBufferDefined && buffer[Symbol.toStringTag] === "SharedArrayBuffer";
}
3 changes: 0 additions & 3 deletions src/mono/wasm/runtime/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,6 @@ function stringToMonoStringNewRoot(string: string, result: WasmRoot<MonoString>)
// When threading is enabled, TextDecoder does not accept a view of a
// SharedArrayBuffer, we must make a copy of the array first.
// See https://github.com/whatwg/encoding/issues/172
// BEWARE: In some cases, `instanceof SharedArrayBuffer` returns false even though buffer is an SAB.
// Patch adapted from https://github.com/emscripten-core/emscripten/pull/16994
// See also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toStringTag
export function viewOrCopy(view: Uint8Array, start: CharPtr, end: CharPtr): Uint8Array {
// this condition should be eliminated by rollup on non-threading builds
const needsCopy = isSharedArrayBuffer(view.buffer);
Expand Down
3 changes: 1 addition & 2 deletions src/mono/wasm/wasm.proj
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,7 @@

<Copy SourceFiles="runtime/driver.c;
runtime/pinvoke.c;
runtime/corebindings.c;
$(SharedNativeRoot)libs\System.Native\pal_random.lib.js;"
runtime/corebindings.c;"
DestinationFolder="$(NativeBinDir)src"
SkipUnchangedFiles="true" />

Expand Down
45 changes: 0 additions & 45 deletions src/native/libs/System.Native/pal_random.lib.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/native/minipal/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ int32_t minipal_get_cryptographically_secure_random_bytes(uint8_t* buffer, int32
assert(buffer != NULL);

#ifdef __EMSCRIPTEN__
extern int32_t dotnet_browser_entropy(uint8_t* buffer, int32_t bufferLength);
extern int32_t mono_wasm_browser_entropy(uint8_t* buffer, int32_t bufferLength);
static bool sMissingBrowserCrypto;
if (!sMissingBrowserCrypto)
{
int32_t bff = dotnet_browser_entropy(buffer, bufferLength);
int32_t bff = mono_wasm_browser_entropy(buffer, bufferLength);
if (bff == -1)
sMissingBrowserCrypto = true;
else
Expand Down

0 comments on commit ee9dd81

Please sign in to comment.