From 1863d351e6f5277882ae9e86ce6274519f969c6f Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 9 Mar 2021 20:35:10 -0800 Subject: [PATCH 01/23] [WIP] - Start crypto worker and initialize channel. --- src/mono/sample/wasm/wasm.mk | 2 +- src/mono/wasm/Makefile | 9 +- src/mono/wasm/build/WasmApp.targets | 2 + src/mono/wasm/runtime/crypto_worker.js | 147 +++++++++++++++++++++++ src/mono/wasm/runtime/library_channel.js | 136 +++++++++++++++++++++ src/mono/wasm/runtime/library_mono.js | 21 ++++ src/mono/wasm/wasm.proj | 1 + 7 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 src/mono/wasm/runtime/crypto_worker.js create mode 100644 src/mono/wasm/runtime/library_channel.js diff --git a/src/mono/sample/wasm/wasm.mk b/src/mono/sample/wasm/wasm.mk index 1858ca3791182..746be79165d9d 100644 --- a/src/mono/sample/wasm/wasm.mk +++ b/src/mono/sample/wasm/wasm.mk @@ -23,7 +23,7 @@ run-browser: echo "The tool dotnet-serve could not be found. Install with: $(DOTNET) tool install --global dotnet-serve"; \ exit 1; \ else \ - $(DOTNET) serve -d bin/$(CONFIG)/AppBundle -p 8000; \ + $(DOTNET) serve -d:bin/$(CONFIG)/AppBundle -p 8000; \ fi run-console: diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index a3e15f8454b0a..49a19144a16b2 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -101,8 +101,8 @@ $(NATIVE_BIN_DIR)/include/wasm: $(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 $(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 $(3) +$(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 runtime/library_channel.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 --post-js runtime/library_channel.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 $(3) $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi @@ -116,13 +116,16 @@ $(BUILDS_OBJ_DIR)/pinvoke.o: runtime/pinvoke.c runtime/pinvoke.h $(BUILDS_OBJ_DI $(BUILDS_OBJ_DIR)/corebindings.o: runtime/corebindings.c | $(BUILDS_OBJ_DIR) $(EMCC) $(EMCC_FLAGS) $(1) -Oz -I$(MONO_INCLUDE_DIR) runtime/corebindings.c -c -o $$@ +$(NATIVE_BIN_DIR)/crypto_worker.js: runtime/crypto_worker.js | $(NATIVE_BIN_DIR) + cp runtime/crypto_worker.js $(NATIVE_BIN_DIR)/crypto_worker.js + $(NATIVE_BIN_DIR)/src/emcc-flags.txt: | $(NATIVE_BIN_DIR)/src Makefile echo "$(call escape_quote,$(EMCC_FLAGS)) $(1) -Oz" > $$@ $(NATIVE_BIN_DIR)/src/emcc-version.txt: $(EMSDK_PATH)/upstream/.emsdk_version | $(NATIVE_BIN_DIR)/src $(EMCC) --version | head -1 > $$@ -build-native: $(NATIVE_BIN_DIR)/dotnet.js $(NATIVE_BIN_DIR)/src/emcc-flags.txt $(NATIVE_BIN_DIR)/src/emcc-version.txt +build-native: $(NATIVE_BIN_DIR)/dotnet.js $(NATIVE_BIN_DIR)/crypto_worker.js $(NATIVE_BIN_DIR)/src/emcc-flags.txt $(NATIVE_BIN_DIR)/src/emcc-version.txt endef diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 0bd700e379a36..3f4b841fb8c04 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -182,12 +182,14 @@ <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.wasm'">true <_HasDotnetJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js'">true + <_HasCryptoWorkerJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'crypto_worker.js'">true + diff --git a/src/mono/wasm/runtime/crypto_worker.js b/src/mono/wasm/runtime/crypto_worker.js new file mode 100644 index 0000000000000..d60cf3dc589a7 --- /dev/null +++ b/src/mono/wasm/runtime/crypto_worker.js @@ -0,0 +1,147 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var ChannelWorker = { + _impl: class { + // BEGIN ChannelOwner contract - shared constants. + STATE_IDX = 0; + MSG_SIZE_IDX = 1; + + STATE_IDLE = 0; + STATE_REQ = 1; + STATE_RESP = 2; + STATE_REQ_P = 3; // Request has multiple parts + STATE_RESP_P = 4; // Response has multiple parts + STATE_AWAIT = 5; // Awaiting the next part + // END ChannelOwner contract - shared constants. + + constructor(comm_buf, msg_buf, msg_char_len) { + this.comm = new Int32Array(comm_buf); + this.msg = new Uint16Array(msg_buf); + this.msg_char_len = msg_char_len; + } + + async await_request(async_call) { + console.log("await_request()"); + + for (;;) { + // Wait for signal to perform operation + Atomics.wait(this.comm, this.STATE_IDX, this.STATE_IDLE); + + // Read in request + var req = this._read_request(); + console.log("Request: " + req); + + // Perform async action based on request + var resp = await async_call(req); + + // Send response + this._send_response(resp); + } + } + + _read_request() { + var request = ""; + for (;;) { + // Get the current state and message size + var state = Atomics.load(this.comm, this.STATE_IDX); + var size_to_read = Atomics.load(this.comm, this.MSG_SIZE_IDX); + + // Append the latest part of the message. + request += this._read_from_msg(0, size_to_read); + + // The request is complete. + if (state === this.STATE_REQ) + break; + + // Reset the size and transition to await state. + Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); + Atomics.store(this.comm, this.STATE_IDX, this.STATE_AWAIT); + Atomics.wait(this.comm, this.STATE_IDX, this.STATE_AWAIT); + } + + return request; + } + + _read_from_msg(begin, end) { + return String.fromCharCode.apply(null, this.msg.slice(begin, end)); + } + + _send_response(msg) { + if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_REQ) + throw "WORKER: Invalid sync communication channel state."; + + var state; // State machine variable + const msg_len = msg.length; + var msg_written = 0; + + for (;;) { + // Write the message and return how much was written. + var wrote = this._write_to_msg(msg, msg_written, msg_len); + msg_written += wrote; + + // Indicate how much was written to the this.msg buffer. + Atomics.store(this.comm, this.MSG_SIZE_IDX, wrote); + + // Indicate if this was the whole message or part of it. + state = msg_written === msg_len ? this.STATE_RESP : this.STATE_RESP_P; + + // Update the state + Atomics.store(this.comm, this.STATE_IDX, state); + + // Wait for the transition to know the main thread has + // received the response by moving onto a new state. + Atomics.wait(this.comm, this.STATE_IDX, state); + + // Done sending response. + if (state === this.STATE_RESP) + break; + } + } + + _write_to_msg(input, start, input_len) { + var mi = 0; + var ii = start; + while (mi < this.msg_char_len && ii < input_len) { + this.msg[mi] = input.charCodeAt(ii); + ii++; // Next character + mi++; // Next buffer index + } + return ii - start; + } + }, + + create: function (comm_buf, msg_buf, msg_char_len) { + return new this._impl(comm_buf, msg_buf, msg_char_len); + } +}; + +// +// [TODO] Handle crypto calls that uses Promises below. +// + +// Operation to perform. +async function async_call(msg) { + var keyPair = await self.crypto.subtle.generateKey( + { + name: "RSA-OAEP", + modulusLength: 2048, + publicExponent: new Uint8Array([1, 0, 1]), + hash: "SHA-256", + }, + true, + ["encrypt", "decrypt"] + ); + + return msg.split("").reverse().join(""); +} + +var s_channel; + +// Initialize WebWorker +onmessage = function (p) { + console.log(p.data.salutation); + s_channel = ChannelWorker.create(p.data.comm_buf, p.data.msg_buf, p.data.msg_char_len); + + s_channel.await_request(async_call); +} diff --git a/src/mono/wasm/runtime/library_channel.js b/src/mono/wasm/runtime/library_channel.js new file mode 100644 index 0000000000000..fd6eac1991378 --- /dev/null +++ b/src/mono/wasm/runtime/library_channel.js @@ -0,0 +1,136 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +Module [ 'channel' ] = { + _impl: class { + // Index constants for the communication buffer. + STATE_IDX = 0; + MSG_SIZE_IDX = 1; + COMM_LAST_IDX = this.MSG_SIZE_IDX; + + // Communication states. + STATE_IDLE = 0; + STATE_REQ = 1; + STATE_RESP = 2; + STATE_REQ_P = 3; // Request has multiple parts + STATE_RESP_P = 4; // Response has multiple parts + STATE_AWAIT = 5; // Awaiting the next part + + constructor(msg_char_len) { + this.msg_char_len = msg_char_len; + + const int_bytes = 4; + const comm_byte_len = int_bytes * (this.COMM_LAST_IDX + 1); + this.comm_buf = new SharedArrayBuffer(comm_byte_len); + + // JavaScript character encoding is UTF-16. + const char_bytes = 2; + const msg_byte_len = char_bytes * this.msg_char_len; + this.msg_buf = new SharedArrayBuffer(msg_byte_len); + + // Create the local arrays to use. + this.comm = new Int32Array(this.comm_buf); + this.msg = new Uint16Array(this.msg_buf); + } + + get_msg_len() { return this.msg_char_len; } + get_msg_buffer() { return this.msg_buf; } + get_comm_buffer() { return this.comm_buf; } + + send_msg(msg) { + if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_IDLE) { + throw "OWNER: Invalid sync communication channel state."; + } + this._send_request(msg); + return this._read_response(); + } + + _send_request(msg) { + var state; + const msg_len = msg.length; + var msg_written = 0; + + for (;;) { + // Write the message and return how much was written. + var wrote = this._write_to_msg(msg, msg_written, msg_len); + msg_written += wrote; + + // Indicate how much was written to the this.msg buffer. + Atomics.store(this.comm, this.MSG_SIZE_IDX, wrote); + + // Indicate if this was the whole message or part of it. + state = msg_written === msg_len ? this.STATE_REQ : this.STATE_REQ_P; + + // Notify webworker + Atomics.store(this.comm, this.STATE_IDX, state); + Atomics.notify(this.comm, this.STATE_IDX); + + // The send message is complete. + if (state === this.STATE_REQ) + break; + + // Wait for the worker to be ready for the next part. + // - Atomics.wait() is not permissible on the main thread. + do { + state = Atomics.load(this.comm, this.STATE_IDX); + } while (state !== this.STATE_AWAIT); + } + } + + _write_to_msg(input, start, input_len) { + var mi = 0; + var ii = start; + while (mi < this.msg_char_len && ii < input_len) { + this.msg[mi] = input.charCodeAt(ii); + ii++; // Next character + mi++; // Next buffer index + } + return ii - start; + } + + _read_response() { + var state; + var response = ""; + for (;;) { + // Wait for webworker response. + // - Atomics.wait() is not permissible on the main thread. + do { + state = Atomics.load(this.comm, this.STATE_IDX); + } while (state !== this.STATE_RESP && state !== this.STATE_RESP_P); + + var size_to_read = Atomics.load(this.comm, this.MSG_SIZE_IDX); + + // Append the latest part of the message. + response += this._read_from_msg(0, size_to_read); + + // The response is complete. + if (state === this.STATE_RESP) + break; + + // Reset the size and transition to await state. + Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); + Atomics.store(this.comm, this.STATE_IDX, this.STATE_AWAIT); + Atomics.notify(this.comm, this.STATE_IDX); + } + + // Reset the communication channel's state and let the + // webworker know we are done. + Atomics.store(this.comm, this.STATE_IDX, this.STATE_IDLE); + Atomics.notify(this.comm, this.STATE_IDX); + + return response; + } + + _read_from_msg(begin, end) { + return String.fromCharCode.apply(null, this.msg.slice(begin, end)); + } + + }, + + create: function (msg_char_len) { + if (msg_char_len === undefined) { + msg_char_len = 1024; // Default size is arbitrary but is in 'char' units (i.e. UTF-16 code points). + } + return new this._impl(msg_char_len); + } +}; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 47b454a8cdcfc..29a76bb3ff0a4 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -55,6 +55,10 @@ var MonoSupportLib = { _vt_stack: [], mono_wasm_runtime_is_ready : false, mono_wasm_ignore_pdb_load_errors: true, + mono_wasm_crypto: { + channel: null, + worker: null + }, /** @type {object.} */ _id_table: {}, @@ -1699,6 +1703,19 @@ var MonoSupportLib = { return Module.ccall ('mono_wasm_get_icudt_name', 'string', ['string'], [culture]); }, + _initialize_workers: function () { + var chan = Module.channel.create(); + var worker = new Worker ("crypto_worker.js"); + worker.postMessage ({ + salutation:"Message from main", + comm_buf: chan.get_comm_buffer(), + msg_buf: chan.get_msg_buffer(), + msg_char_len: chan.get_msg_len() + }); + MONO.mono_wasm_crypto.channel = chan; + MONO.mono_wasm_crypto.worker = worker; + }, + _finalize_startup: function (args, ctx) { var loaded_files_with_debug_info = []; @@ -1736,6 +1753,10 @@ var MonoSupportLib = { tz = Intl.DateTimeFormat().resolvedOptions().timeZone; } catch {} MONO.mono_wasm_setenv ("TZ", tz || "UTC"); + + // Now that the runtime has been loaded, spin off any web workers needed + // for ancillary operations. + MONO._initialize_workers (); MONO.mono_wasm_runtime_ready (); args.loaded_cb (); }, diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index f78fd846ae621..42d73c6cfa17b 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -92,6 +92,7 @@ Date: Wed, 10 Mar 2021 12:01:31 -0800 Subject: [PATCH 02/23] Make Emscripten minimizer happy by using getters instead of fields. --- src/mono/wasm/runtime/crypto_worker.js | 19 ++++++++++--------- src/mono/wasm/runtime/library_channel.js | 18 +++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/mono/wasm/runtime/crypto_worker.js b/src/mono/wasm/runtime/crypto_worker.js index d60cf3dc589a7..633ad842feada 100644 --- a/src/mono/wasm/runtime/crypto_worker.js +++ b/src/mono/wasm/runtime/crypto_worker.js @@ -4,15 +4,16 @@ var ChannelWorker = { _impl: class { // BEGIN ChannelOwner contract - shared constants. - STATE_IDX = 0; - MSG_SIZE_IDX = 1; - - STATE_IDLE = 0; - STATE_REQ = 1; - STATE_RESP = 2; - STATE_REQ_P = 3; // Request has multiple parts - STATE_RESP_P = 4; // Response has multiple parts - STATE_AWAIT = 5; // Awaiting the next part + get STATE_IDX() { return 0; } + get MSG_SIZE_IDX() { return 1; } + + // Communication states. + get STATE_IDLE() { return 0; } + get STATE_REQ() { return 1; } + get STATE_RESP() { return 2; } + get STATE_REQ_P() { return 3; } // Request has multiple parts + get STATE_RESP_P() { return 4; } // Response has multiple parts + get STATE_AWAIT() { return 5; } // Awaiting the next part // END ChannelOwner contract - shared constants. constructor(comm_buf, msg_buf, msg_char_len) { diff --git a/src/mono/wasm/runtime/library_channel.js b/src/mono/wasm/runtime/library_channel.js index fd6eac1991378..17e95d6a2e14b 100644 --- a/src/mono/wasm/runtime/library_channel.js +++ b/src/mono/wasm/runtime/library_channel.js @@ -4,17 +4,17 @@ Module [ 'channel' ] = { _impl: class { // Index constants for the communication buffer. - STATE_IDX = 0; - MSG_SIZE_IDX = 1; - COMM_LAST_IDX = this.MSG_SIZE_IDX; + get STATE_IDX() { return 0; } + get MSG_SIZE_IDX() { return 1; } + get COMM_LAST_IDX() { return this.MSG_SIZE_IDX; } // Communication states. - STATE_IDLE = 0; - STATE_REQ = 1; - STATE_RESP = 2; - STATE_REQ_P = 3; // Request has multiple parts - STATE_RESP_P = 4; // Response has multiple parts - STATE_AWAIT = 5; // Awaiting the next part + get STATE_IDLE() { return 0; } + get STATE_REQ() { return 1; } + get STATE_RESP() { return 2; } + get STATE_REQ_P() { return 3; } // Request has multiple parts + get STATE_RESP_P() { return 4; } // Response has multiple parts + get STATE_AWAIT() { return 5; } // Awaiting the next part constructor(msg_char_len) { this.msg_char_len = msg_char_len; From 4e2d7386849b4aba7db22786e681ce9d930f4bb2 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Wed, 10 Mar 2021 22:43:04 -0800 Subject: [PATCH 03/23] Add new System.Security.Cryptography.Native.Browser library. Consume the library via new P/Invokes in a Browser impl of the Crypto API. Tell the WASM build about System.Security.Cryptography.Native.Browser in order to generated the pinvoke-table. Defer to the Crypto worker for SHA hashing functions. --- .../src/Interop/Browser/Interop.Libraries.cs | 12 + .../Interop.SHAHash.cs | 28 + .../pal_browser.h | 18 + .../pal_crypto_webworker.c | 23 + .../pal_crypto_webworker.h | 21 + .../pal_crypto_webworker.js | 28 + src/libraries/Native/Unix/CMakeLists.txt | 2 +- .../CMakeLists.txt | 18 + src/libraries/Native/Windows/CMakeLists.txt | 4 + .../CMakeLists.txt | 0 .../Cryptography/SHAHashProvider.Browser.cs | 969 +----------------- ...em.Security.Cryptography.Algorithms.csproj | 7 +- src/mono/wasm/Makefile | 10 +- src/mono/wasm/runtime/crypto_worker.js | 53 +- src/mono/wasm/runtime/library_channel.js | 1 - src/mono/wasm/wasm.proj | 1 + 16 files changed, 214 insertions(+), 981 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs create mode 100644 src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs create mode 100644 src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_browser.h create mode 100644 src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c create mode 100644 src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h create mode 100644 src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js create mode 100644 src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt create mode 100644 src/libraries/Native/Windows/System.Security.Cryptography.Native.Browser/CMakeLists.txt diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs b/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs new file mode 100644 index 0000000000000..b28d723f0bfc9 --- /dev/null +++ b/src/libraries/Common/src/Interop/Browser/Interop.Libraries.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +internal static partial class Interop +{ + internal static partial class Libraries + { + // Shims + internal const string SystemNative = "libSystem.Native"; + internal const string CryptoNative = "libSystem.Security.Cryptography.Native.Browser"; + } +} diff --git a/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs new file mode 100644 index 0000000000000..f7e6756b7a3e4 --- /dev/null +++ b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class BrowserCrypto + { + internal enum ShaHash + { + Sha1, + Sha256, + Sha384, + Sha512, + }; + + [DllImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_SHAHash")] + internal static extern unsafe int SHAHash( + ShaHash hash, + byte* input_buffer, + int input_len, + byte* output_buffer, + int output_len); + } +} diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_browser.h b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_browser.h new file mode 100644 index 0000000000000..775fe634536e2 --- /dev/null +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_browser.h @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include + +#ifndef __EMSCRIPTEN__ +#error Cryptography Native Browser is designed to be compiled with Emscripten. +#endif // __EMSCRIPTEN__ + +#ifndef PALEXPORT +#ifdef TARGET_UNIX +#define PALEXPORT __attribute__ ((__visibility__ ("default"))) +#else +#define PALEXPORT __declspec(dllexport) +#endif +#endif // PALEXPORT diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c new file mode 100644 index 0000000000000..0ef32519500f5 --- /dev/null +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal_browser.h" +#include "pal_crypto_webworker.h" + +// Forward declarations +extern int32_t dotnet_browser_sha_hash( + enum sha_hash ver, + uint8_t* input_buffer, + int32_t input_len, + uint8_t* output_buffer, + int32_t output_len); + +int32_t SystemCryptoNativeBrowser_SHAHash( + enum sha_hash ver, + uint8_t* input_buffer, + int32_t input_len, + uint8_t* output_buffer, + int32_t output_len) +{ + return dotnet_browser_sha_hash(ver, input_buffer, input_len, output_buffer, output_len); +} diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h new file mode 100644 index 0000000000000..d60d3a3c067a9 --- /dev/null +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include + +enum sha_hash +{ + sha_hash_1, + sha_hash_256, + sha_hash_384, + sha_hash_512, +}; + +PALEXPORT int32_t SystemCryptoNativeBrowser_SHAHash( + enum sha_hash ver, + uint8_t* input_buffer, + int32_t input_len, + uint8_t* output_buffer, + int32_t output_len); diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js new file mode 100644 index 0000000000000..c52f4af363568 --- /dev/null +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var CryptoWebWorkerLib = { + $CRYPTOWEBWORKER: { + call_sha_hash: function(sha_hash, input_buffer, input_len, output_buffer, output_len) { + var msg = { + func: "sha", + type: sha_hash, + data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len)) + }; + var response = MONO.mono_wasm_crypto.channel.send_msg(JSON.stringify(msg)); + var digest = JSON.parse(response); + if (digest.length !== output_len) { + throw "SHA HASH: Unexpected output length"; + } + + Module.HEAPU8.set(digest, output_buffer); + return 1; + } + }, + dotnet_browser_sha_hash: function (sha_hash, input_buffer, input_len, output_buffer, output_len) { + return CRYPTOWEBWORKER.call_sha_hash(sha_hash, input_buffer, input_len, output_buffer, output_len); + }, +}; + +autoAddDeps(CryptoWebWorkerLib, '$CRYPTOWEBWORKER') +mergeInto(LibraryManager.library, CryptoWebWorkerLib) diff --git a/src/libraries/Native/Unix/CMakeLists.txt b/src/libraries/Native/Unix/CMakeLists.txt index fab7c06dfc3d1..486637a067ec1 100644 --- a/src/libraries/Native/Unix/CMakeLists.txt +++ b/src/libraries/Native/Unix/CMakeLists.txt @@ -241,7 +241,7 @@ endif() add_subdirectory(System.Native) if(CLR_CMAKE_TARGET_BROWSER) - # skip for now + add_subdirectory(System.Security.Cryptography.Native.Browser) elseif(CLR_CMAKE_TARGET_MACCATALYST) add_subdirectory(System.Net.Security.Native) # System.Security.Cryptography.Native is intentionally disabled on iOS diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt new file mode 100644 index 0000000000000..46c346602d2ea --- /dev/null +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt @@ -0,0 +1,18 @@ +project(System.Security.Cryptography.Native.Browser C) + +set(ANYOS_SOURCES_DIR ../../AnyOS/System.Security.Cryptography.Native.Browser) +include_directories("${ANYOS_SOURCES_DIR}") + +set (NATIVE_SOURCES + ${ANYOS_SOURCES_DIR}/pal_crypto_webworker.c +) + +add_library (System.Security.Cryptography.Native.Browser-Static + STATIC + ${NATIVE_SOURCES} + ${VERSION_FILE_PATH} +) + +set_target_properties(System.Security.Cryptography.Native.Browser-Static PROPERTIES OUTPUT_NAME System.Security.Cryptography.Native.Browser CLEAN_DIRECT_OUTPUT 1) + +install (TARGETS System.Security.Cryptography.Native.Browser-Static DESTINATION ${STATIC_LIB_DESTINATION}) \ No newline at end of file diff --git a/src/libraries/Native/Windows/CMakeLists.txt b/src/libraries/Native/Windows/CMakeLists.txt index 3f9924adb0a9d..c5b0594fe14ac 100644 --- a/src/libraries/Native/Windows/CMakeLists.txt +++ b/src/libraries/Native/Windows/CMakeLists.txt @@ -130,3 +130,7 @@ if(STATIC_LIBS_ONLY) endif() add_subdirectory(System.IO.Compression.Native) + +if (CLR_CMAKE_TARGET_BROWSER) + add_subdirectory(System.SecurityCryptography.Native.Browser) +endif (CLR_CMAKE_TARGET_BROWSER) diff --git a/src/libraries/Native/Windows/System.Security.Cryptography.Native.Browser/CMakeLists.txt b/src/libraries/Native/Windows/System.Security.Cryptography.Native.Browser/CMakeLists.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs index c87500a56e5dd..b3094a1cb0eba 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs @@ -11,8 +11,8 @@ namespace Internal.Cryptography { internal sealed class SHAHashProvider : HashProvider { - private int hashSizeInBytes; - private SHAManagedImplementationBase impl; + private readonly int hashSizeInBytes; + private readonly Interop.BrowserCrypto.ShaHash impl; private MemoryStream buffer; public SHAHashProvider(string hashAlgorithmId) @@ -20,19 +20,19 @@ public SHAHashProvider(string hashAlgorithmId) switch (hashAlgorithmId) { case HashAlgorithmNames.SHA1: - impl = new SHA1ManagedImplementation(); + impl = Interop.BrowserCrypto.ShaHash.Sha1; hashSizeInBytes = 20; break; case HashAlgorithmNames.SHA256: - impl = new SHA256ManagedImplementation(); + impl = Interop.BrowserCrypto.ShaHash.Sha256; hashSizeInBytes = 32; break; case HashAlgorithmNames.SHA384: - impl = new SHA384ManagedImplementation(); + impl = Interop.BrowserCrypto.ShaHash.Sha384; hashSizeInBytes = 48; break; case HashAlgorithmNames.SHA512: - impl = new SHA512ManagedImplementation(); + impl = Interop.BrowserCrypto.ShaHash.Sha512; hashSizeInBytes = 64; break; default: @@ -62,965 +62,30 @@ public override int GetCurrentHash(Span destination) { Debug.Assert(destination.Length >= hashSizeInBytes); - impl.Initialize(); + byte[] srcArray = Array.Empty(); + int srcLength = 0; if (buffer != null) { - impl.HashCore(buffer.GetBuffer(), 0, (int)buffer.Length); + srcArray = buffer.GetBuffer(); + srcLength = (int)buffer.Length; } - impl.HashFinal().CopyTo(destination); - return hashSizeInBytes; - } - - public override int HashSizeInBytes => hashSizeInBytes; - - public override void Dispose(bool disposing) - { - } - - private abstract class SHAManagedImplementationBase - { - public abstract void Initialize(); - public abstract void HashCore(byte[] partIn, int ibStart, int cbSize); - public abstract byte[] HashFinal(); - } - - private class SHA1ManagedImplementation : SHAManagedImplementationBase - { - // It's ok to use a "non-secret purposes" hashing implementation here, as this is only - // used in wasm scenarios, and as of the current release we don't make any security guarantees - // about our crypto primitives in wasm environments. - private Sha1ForNonSecretPurposes _state; // mutable struct - don't make readonly - - public override void Initialize() - { - _state = default; - _state.Start(); - } - - public override void HashCore(byte[] partIn, int ibStart, int cbSize) - { - _state.Append(partIn.AsSpan(ibStart, cbSize)); - } - - public override byte[] HashFinal() - { - byte[] output = new byte[20]; - _state.Finish(output); - return output; - } - } - - // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha256managed.cs - private class SHA256ManagedImplementation : SHAManagedImplementationBase - { - private byte[] _buffer; - private long _count; // Number of bytes in the hashed message - private uint[] _stateSHA256; - private uint[] _W; - - public SHA256ManagedImplementation() - { - _stateSHA256 = new uint[8]; - _buffer = new byte[64]; - _W = new uint[64]; - - InitializeState(); - } - - public override void Initialize() - { - InitializeState(); - - // Zeroize potentially sensitive information. - Array.Clear(_buffer, 0, _buffer.Length); - Array.Clear(_W, 0, _W.Length); - } - - private void InitializeState() - { - _count = 0; - - _stateSHA256[0] = 0x6a09e667; - _stateSHA256[1] = 0xbb67ae85; - _stateSHA256[2] = 0x3c6ef372; - _stateSHA256[3] = 0xa54ff53a; - _stateSHA256[4] = 0x510e527f; - _stateSHA256[5] = 0x9b05688c; - _stateSHA256[6] = 0x1f83d9ab; - _stateSHA256[7] = 0x5be0cd19; - } - - /* SHA256 block update operation. Continues an SHA message-digest - operation, processing another message block, and updating the - context. - */ - public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize) + unsafe { - int bufferLen; - int partInLen = cbSize; - int partInBase = ibStart; - - /* Compute length of buffer */ - bufferLen = (int)(_count & 0x3f); - - /* Update number of bytes */ - _count += partInLen; - - fixed (uint* stateSHA256 = _stateSHA256) + fixed (byte* src = srcArray) + fixed (byte* dest = destination) { - fixed (byte* buffer = _buffer) - { - fixed (uint* expandedBuffer = _W) - { - if ((bufferLen > 0) && (bufferLen + partInLen >= 64)) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 64 - bufferLen); - partInBase += (64 - bufferLen); - partInLen -= (64 - bufferLen); - SHATransform(expandedBuffer, stateSHA256, buffer); - bufferLen = 0; - } - - /* Copy input to temporary buffer and hash */ - while (partInLen >= 64) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 64); - partInBase += 64; - partInLen -= 64; - SHATransform(expandedBuffer, stateSHA256, buffer); - } - - if (partInLen > 0) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen); - } - } - } + Interop.BrowserCrypto.SHAHash(impl, src, srcLength, dest, destination.Length); } } - /* SHA256 finalization. Ends an SHA256 message-digest operation, writing - the message digest. - */ - public override byte[] HashFinal() - { - byte[] pad; - int padLen; - long bitCount; - byte[] hash = new byte[32]; // HashSizeValue = 256 - - /* Compute padding: 80 00 00 ... 00 00 - */ - - padLen = 64 - (int)(_count & 0x3f); - if (padLen <= 8) - padLen += 64; - - pad = new byte[padLen]; - pad[0] = 0x80; - - // Convert count to bit count - bitCount = _count * 8; - - pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff); - pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff); - pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff); - pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff); - pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff); - pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff); - pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff); - pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff); - - /* Digest padding */ - HashCore(pad, 0, pad.Length); - - /* Store digest */ - SHAUtils.DWORDToBigEndian(hash, _stateSHA256, 8); - - return hash; - } - - private static readonly uint[] _K = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, - 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, - 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, - 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - - private static unsafe void SHATransform(uint* expandedBuffer, uint* state, byte* block) - { - uint a, b, c, d, e, f, h, g; - uint aa, bb, cc, dd, ee, ff, hh, gg; - uint T1; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - f = state[5]; - g = state[6]; - h = state[7]; - - // fill in the first 16 bytes of W. - SHAUtils.DWORDFromBigEndian(expandedBuffer, 16, block); - SHA256Expand(expandedBuffer); - - /* Apply the SHA256 compression function */ - // We are trying to be smart here and avoid as many copies as we can - // The perf gain with this method over the straightforward modify and shift - // forward is >= 20%, so it's worth the pain - for (int j = 0; j < 64;) - { - T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j]; - ee = d + T1; - aa = T1 + Sigma_0(a) + Maj(a, b, c); - j++; - - T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j]; - ff = c + T1; - bb = T1 + Sigma_0(aa) + Maj(aa, a, b); - j++; - - T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j]; - gg = b + T1; - cc = T1 + Sigma_0(bb) + Maj(bb, aa, a); - j++; - - T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j]; - hh = a + T1; - dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa); - j++; - - T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j]; - h = aa + T1; - d = T1 + Sigma_0(dd) + Maj(dd, cc, bb); - j++; - - T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j]; - g = bb + T1; - c = T1 + Sigma_0(d) + Maj(d, dd, cc); - j++; - - T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j]; - f = cc + T1; - b = T1 + Sigma_0(c) + Maj(c, d, dd); - j++; - - T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j]; - e = dd + T1; - a = T1 + Sigma_0(b) + Maj(b, c, d); - j++; - } - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; - } - - private static uint RotateRight(uint x, int n) - { - return (((x) >> (n)) | ((x) << (32 - (n)))); - } - - private static uint Ch(uint x, uint y, uint z) - { - return ((x & y) ^ ((x ^ 0xffffffff) & z)); - } - - private static uint Maj(uint x, uint y, uint z) - { - return ((x & y) ^ (x & z) ^ (y & z)); - } - - private static uint sigma_0(uint x) - { - return (RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3)); - } - - private static uint sigma_1(uint x) - { - return (RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10)); - } - - private static uint Sigma_0(uint x) - { - return (RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22)); - } - - private static uint Sigma_1(uint x) - { - return (RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25)); - } - - /* This function creates W_16,...,W_63 according to the formula - W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16}; - */ - private static unsafe void SHA256Expand(uint* x) - { - for (int i = 16; i < 64; i++) - { - x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16]; - } - } - } - - // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha384managed.cs - private class SHA384ManagedImplementation : SHAManagedImplementationBase - { - private byte[] _buffer; - private ulong _count; // Number of bytes in the hashed message - private ulong[] _stateSHA384; - private ulong[] _W; - - public SHA384ManagedImplementation() - { - _stateSHA384 = new ulong[8]; - _buffer = new byte[128]; - _W = new ulong[80]; - - InitializeState(); - } - - public override void Initialize() - { - InitializeState(); - - // Zeroize potentially sensitive information. - Array.Clear(_buffer, 0, _buffer.Length); - Array.Clear(_W, 0, _W.Length); - } - - private void InitializeState() - { - _count = 0; - - _stateSHA384[0] = 0xcbbb9d5dc1059ed8; - _stateSHA384[1] = 0x629a292a367cd507; - _stateSHA384[2] = 0x9159015a3070dd17; - _stateSHA384[3] = 0x152fecd8f70e5939; - _stateSHA384[4] = 0x67332667ffc00b31; - _stateSHA384[5] = 0x8eb44a8768581511; - _stateSHA384[6] = 0xdb0c2e0d64f98fa7; - _stateSHA384[7] = 0x47b5481dbefa4fa4; - } - - /* SHA384 block update operation. Continues an SHA message-digest - operation, processing another message block, and updating the - context. - */ - public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize) - { - int bufferLen; - int partInLen = cbSize; - int partInBase = ibStart; - - /* Compute length of buffer */ - bufferLen = (int)(_count & 0x7f); - - /* Update number of bytes */ - _count += (ulong)partInLen; - - fixed (ulong* stateSHA384 = _stateSHA384) - { - fixed (byte* buffer = _buffer) - { - fixed (ulong* expandedBuffer = _W) - { - if ((bufferLen > 0) && (bufferLen + partInLen >= 128)) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 128 - bufferLen); - partInBase += (128 - bufferLen); - partInLen -= (128 - bufferLen); - SHATransform(expandedBuffer, stateSHA384, buffer); - bufferLen = 0; - } - - /* Copy input to temporary buffer and hash */ - while (partInLen >= 128) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 128); - partInBase += 128; - partInLen -= 128; - SHATransform(expandedBuffer, stateSHA384, buffer); - } - - if (partInLen > 0) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen); - } - } - } - } - } - - /* SHA384 finalization. Ends an SHA384 message-digest operation, writing - the message digest. - */ - public override byte[] HashFinal() - { - byte[] pad; - int padLen; - ulong bitCount; - byte[] hash = new byte[48]; // HashSizeValue = 384 - - /* Compute padding: 80 00 00 ... 00 00 - */ - - padLen = 128 - (int)(_count & 0x7f); - if (padLen <= 16) - padLen += 128; - - pad = new byte[padLen]; - pad[0] = 0x80; - - // Convert count to bit count - bitCount = _count * 8; - - // bitCount is at most 8 * 128 = 1024. Its representation as a 128-bit number has all bits set to zero - // except eventually the 11 lower bits - - //pad[padLen-16] = (byte) ((bitCount >> 120) & 0xff); - //pad[padLen-15] = (byte) ((bitCount >> 112) & 0xff); - //pad[padLen-14] = (byte) ((bitCount >> 104) & 0xff); - //pad[padLen-13] = (byte) ((bitCount >> 96) & 0xff); - //pad[padLen-12] = (byte) ((bitCount >> 88) & 0xff); - //pad[padLen-11] = (byte) ((bitCount >> 80) & 0xff); - //pad[padLen-10] = (byte) ((bitCount >> 72) & 0xff); - //pad[padLen-9] = (byte) ((bitCount >> 64) & 0xff); - pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff); - pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff); - pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff); - pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff); - pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff); - pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff); - pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff); - pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff); - - /* Digest padding */ - HashCore(pad, 0, pad.Length); - - /* Store digest */ - SHAUtils.QuadWordToBigEndian(hash, _stateSHA384, 6); - - return hash; - } - - private static readonly ulong[] _K = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, - }; - - private static unsafe void SHATransform(ulong* expandedBuffer, ulong* state, byte* block) - { - ulong a, b, c, d, e, f, g, h; - ulong aa, bb, cc, dd, ee, ff, hh, gg; - ulong T1; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - f = state[5]; - g = state[6]; - h = state[7]; - - // fill in the first 16 blocks of W. - SHAUtils.QuadWordFromBigEndian(expandedBuffer, 16, block); - SHA384Expand(expandedBuffer); - - /* Apply the SHA384 compression function */ - // We are trying to be smart here and avoid as many copies as we can - // The perf gain with this method over the straightforward modify and shift - // forward is >= 20%, so it's worth the pain - for (int j = 0; j < 80;) - { - T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j]; - ee = d + T1; - aa = T1 + Sigma_0(a) + Maj(a, b, c); - j++; - - T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j]; - ff = c + T1; - bb = T1 + Sigma_0(aa) + Maj(aa, a, b); - j++; - - T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j]; - gg = b + T1; - cc = T1 + Sigma_0(bb) + Maj(bb, aa, a); - j++; - - T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j]; - hh = a + T1; - dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa); - j++; - - T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j]; - h = aa + T1; - d = T1 + Sigma_0(dd) + Maj(dd, cc, bb); - j++; - - T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j]; - g = bb + T1; - c = T1 + Sigma_0(d) + Maj(d, dd, cc); - j++; - - T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j]; - f = cc + T1; - b = T1 + Sigma_0(c) + Maj(c, d, dd); - j++; - - T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j]; - e = dd + T1; - a = T1 + Sigma_0(b) + Maj(b, c, d); - j++; - } - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; - } - - private static ulong RotateRight(ulong x, int n) - { - return (((x) >> (n)) | ((x) << (64 - (n)))); - } - - private static ulong Ch(ulong x, ulong y, ulong z) - { - return ((x & y) ^ ((x ^ 0xffffffffffffffff) & z)); - } - - private static ulong Maj(ulong x, ulong y, ulong z) - { - return ((x & y) ^ (x & z) ^ (y & z)); - } - - private static ulong Sigma_0(ulong x) - { - return (RotateRight(x, 28) ^ RotateRight(x, 34) ^ RotateRight(x, 39)); - } - - private static ulong Sigma_1(ulong x) - { - return (RotateRight(x, 14) ^ RotateRight(x, 18) ^ RotateRight(x, 41)); - } - - private static ulong sigma_0(ulong x) - { - return (RotateRight(x, 1) ^ RotateRight(x, 8) ^ (x >> 7)); - } - - private static ulong sigma_1(ulong x) - { - return (RotateRight(x, 19) ^ RotateRight(x, 61) ^ (x >> 6)); - } - - /* This function creates W_16,...,W_79 according to the formula - W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16}; - */ - private static unsafe void SHA384Expand(ulong* x) - { - for (int i = 16; i < 80; i++) - { - x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16]; - } - } + return hashSizeInBytes; } - // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/sha512managed.cs - private class SHA512ManagedImplementation : SHAManagedImplementationBase - { - private byte[] _buffer; - private ulong _count; // Number of bytes in the hashed message - private ulong[] _stateSHA512; - private ulong[] _W; - - public SHA512ManagedImplementation() - { - _stateSHA512 = new ulong[8]; - _buffer = new byte[128]; - _W = new ulong[80]; - - InitializeState(); - } - - public override void Initialize() - { - InitializeState(); - - // Zeroize potentially sensitive information. - Array.Clear(_buffer, 0, _buffer.Length); - Array.Clear(_W, 0, _W.Length); - } - - private void InitializeState() - { - _count = 0; - - _stateSHA512[0] = 0x6a09e667f3bcc908; - _stateSHA512[1] = 0xbb67ae8584caa73b; - _stateSHA512[2] = 0x3c6ef372fe94f82b; - _stateSHA512[3] = 0xa54ff53a5f1d36f1; - _stateSHA512[4] = 0x510e527fade682d1; - _stateSHA512[5] = 0x9b05688c2b3e6c1f; - _stateSHA512[6] = 0x1f83d9abfb41bd6b; - _stateSHA512[7] = 0x5be0cd19137e2179; - } - - /* SHA512 block update operation. Continues an SHA message-digest - operation, processing another message block, and updating the - context. - */ - public override unsafe void HashCore(byte[] partIn, int ibStart, int cbSize) - { - int bufferLen; - int partInLen = cbSize; - int partInBase = ibStart; - - /* Compute length of buffer */ - bufferLen = (int)(_count & 0x7f); - - /* Update number of bytes */ - _count += (ulong)partInLen; - - fixed (ulong* stateSHA512 = _stateSHA512) - { - fixed (byte* buffer = _buffer) - { - fixed (ulong* expandedBuffer = _W) - { - if ((bufferLen > 0) && (bufferLen + partInLen >= 128)) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, 128 - bufferLen); - partInBase += (128 - bufferLen); - partInLen -= (128 - bufferLen); - SHATransform(expandedBuffer, stateSHA512, buffer); - bufferLen = 0; - } - - /* Copy input to temporary buffer and hash */ - while (partInLen >= 128) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, 0, 128); - partInBase += 128; - partInLen -= 128; - SHATransform(expandedBuffer, stateSHA512, buffer); - } - - if (partInLen > 0) - { - Buffer.BlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen); - } - } - } - } - } - - /* SHA512 finalization. Ends an SHA512 message-digest operation, writing - the message digest. - */ - public override byte[] HashFinal() - { - byte[] pad; - int padLen; - ulong bitCount; - byte[] hash = new byte[64]; // HashSizeValue = 512 - - /* Compute padding: 80 00 00 ... 00 00 - */ - - padLen = 128 - (int)(_count & 0x7f); - if (padLen <= 16) - padLen += 128; - - pad = new byte[padLen]; - pad[0] = 0x80; - - // Convert count to bit count - bitCount = _count * 8; - - // If we ever have UInt128 for bitCount, then these need to be uncommented. - // Note that C# only looks at the low 6 bits of the shift value for ulongs, - // so >>0 and >>64 are equal! - - //pad[padLen-16] = (byte) ((bitCount >> 120) & 0xff); - //pad[padLen-15] = (byte) ((bitCount >> 112) & 0xff); - //pad[padLen-14] = (byte) ((bitCount >> 104) & 0xff); - //pad[padLen-13] = (byte) ((bitCount >> 96) & 0xff); - //pad[padLen-12] = (byte) ((bitCount >> 88) & 0xff); - //pad[padLen-11] = (byte) ((bitCount >> 80) & 0xff); - //pad[padLen-10] = (byte) ((bitCount >> 72) & 0xff); - //pad[padLen-9] = (byte) ((bitCount >> 64) & 0xff); - pad[padLen - 8] = (byte)((bitCount >> 56) & 0xff); - pad[padLen - 7] = (byte)((bitCount >> 48) & 0xff); - pad[padLen - 6] = (byte)((bitCount >> 40) & 0xff); - pad[padLen - 5] = (byte)((bitCount >> 32) & 0xff); - pad[padLen - 4] = (byte)((bitCount >> 24) & 0xff); - pad[padLen - 3] = (byte)((bitCount >> 16) & 0xff); - pad[padLen - 2] = (byte)((bitCount >> 8) & 0xff); - pad[padLen - 1] = (byte)((bitCount >> 0) & 0xff); - - /* Digest padding */ - HashCore(pad, 0, pad.Length); - - /* Store digest */ - SHAUtils.QuadWordToBigEndian(hash, _stateSHA512, 8); - - return hash; - } - - private static readonly ulong[] _K = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, - }; - - private static unsafe void SHATransform(ulong* expandedBuffer, ulong* state, byte* block) - { - ulong a, b, c, d, e, f, g, h; - ulong aa, bb, cc, dd, ee, ff, hh, gg; - ulong T1; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - f = state[5]; - g = state[6]; - h = state[7]; - - // fill in the first 16 blocks of W. - SHAUtils.QuadWordFromBigEndian(expandedBuffer, 16, block); - SHA512Expand(expandedBuffer); - - /* Apply the SHA512 compression function */ - // We are trying to be smart here and avoid as many copies as we can - // The perf gain with this method over the straightforward modify and shift - // forward is >= 20%, so it's worth the pain - for (int j = 0; j < 80;) - { - T1 = h + Sigma_1(e) + Ch(e, f, g) + _K[j] + expandedBuffer[j]; - ee = d + T1; - aa = T1 + Sigma_0(a) + Maj(a, b, c); - j++; - - T1 = g + Sigma_1(ee) + Ch(ee, e, f) + _K[j] + expandedBuffer[j]; - ff = c + T1; - bb = T1 + Sigma_0(aa) + Maj(aa, a, b); - j++; - - T1 = f + Sigma_1(ff) + Ch(ff, ee, e) + _K[j] + expandedBuffer[j]; - gg = b + T1; - cc = T1 + Sigma_0(bb) + Maj(bb, aa, a); - j++; - - T1 = e + Sigma_1(gg) + Ch(gg, ff, ee) + _K[j] + expandedBuffer[j]; - hh = a + T1; - dd = T1 + Sigma_0(cc) + Maj(cc, bb, aa); - j++; - - T1 = ee + Sigma_1(hh) + Ch(hh, gg, ff) + _K[j] + expandedBuffer[j]; - h = aa + T1; - d = T1 + Sigma_0(dd) + Maj(dd, cc, bb); - j++; - - T1 = ff + Sigma_1(h) + Ch(h, hh, gg) + _K[j] + expandedBuffer[j]; - g = bb + T1; - c = T1 + Sigma_0(d) + Maj(d, dd, cc); - j++; - - T1 = gg + Sigma_1(g) + Ch(g, h, hh) + _K[j] + expandedBuffer[j]; - f = cc + T1; - b = T1 + Sigma_0(c) + Maj(c, d, dd); - j++; - - T1 = hh + Sigma_1(f) + Ch(f, g, h) + _K[j] + expandedBuffer[j]; - e = dd + T1; - a = T1 + Sigma_0(b) + Maj(b, c, d); - j++; - } - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - state[5] += f; - state[6] += g; - state[7] += h; - } - - private static ulong RotateRight(ulong x, int n) - { - return (((x) >> (n)) | ((x) << (64 - (n)))); - } - - private static ulong Ch(ulong x, ulong y, ulong z) - { - return ((x & y) ^ ((x ^ 0xffffffffffffffff) & z)); - } - - private static ulong Maj(ulong x, ulong y, ulong z) - { - return ((x & y) ^ (x & z) ^ (y & z)); - } - - private static ulong Sigma_0(ulong x) - { - return (RotateRight(x, 28) ^ RotateRight(x, 34) ^ RotateRight(x, 39)); - } - - private static ulong Sigma_1(ulong x) - { - return (RotateRight(x, 14) ^ RotateRight(x, 18) ^ RotateRight(x, 41)); - } - - private static ulong sigma_0(ulong x) - { - return (RotateRight(x, 1) ^ RotateRight(x, 8) ^ (x >> 7)); - } - - private static ulong sigma_1(ulong x) - { - return (RotateRight(x, 19) ^ RotateRight(x, 61) ^ (x >> 6)); - } - - /* This function creates W_16,...,W_79 according to the formula - W_j <- sigma_1(W_{j-2}) + W_{j-7} + sigma_0(W_{j-15}) + W_{j-16}; - */ - private static unsafe void SHA512Expand(ulong* x) - { - for (int i = 16; i < 80; i++) - { - x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16]; - } - } - } + public override int HashSizeInBytes => hashSizeInBytes; - // ported from https://github.com/microsoft/referencesource/blob/a48449cb48a9a693903668a71449ac719b76867c/mscorlib/system/security/cryptography/utils.cs - private class SHAUtils + public override void Dispose(bool disposing) { - // digits == number of DWORDs - public static unsafe void DWORDFromBigEndian(uint* x, int digits, byte* block) - { - int i; - int j; - - for (i = 0, j = 0; i < digits; i++, j += 4) - x[i] = (uint)((block[j] << 24) | (block[j + 1] << 16) | (block[j + 2] << 8) | block[j + 3]); - } - - // encodes x (DWORD) into block (unsigned char), most significant byte first. - // digits == number of DWORDs - public static void DWORDToBigEndian(byte[] block, uint[] x, int digits) - { - int i; - int j; - - for (i = 0, j = 0; i < digits; i++, j += 4) - { - block[j] = (byte)((x[i] >> 24) & 0xff); - block[j + 1] = (byte)((x[i] >> 16) & 0xff); - block[j + 2] = (byte)((x[i] >> 8) & 0xff); - block[j + 3] = (byte)(x[i] & 0xff); - } - } - - // digits == number of QWORDs - public static unsafe void QuadWordFromBigEndian(ulong* x, int digits, byte* block) - { - int i; - int j; - - for (i = 0, j = 0; i < digits; i++, j += 8) - x[i] = ( - (((ulong)block[j]) << 56) | (((ulong)block[j + 1]) << 48) | - (((ulong)block[j + 2]) << 40) | (((ulong)block[j + 3]) << 32) | - (((ulong)block[j + 4]) << 24) | (((ulong)block[j + 5]) << 16) | - (((ulong)block[j + 6]) << 8) | ((ulong)block[j + 7]) - ); - } - - // encodes x (DWORD) into block (unsigned char), most significant byte first. - // digits = number of QWORDS - public static void QuadWordToBigEndian(byte[] block, ulong[] x, int digits) - { - int i; - int j; - - for (i = 0, j = 0; i < digits; i++, j += 8) - { - block[j] = (byte)((x[i] >> 56) & 0xff); - block[j + 1] = (byte)((x[i] >> 48) & 0xff); - block[j + 2] = (byte)((x[i] >> 40) & 0xff); - block[j + 3] = (byte)((x[i] >> 32) & 0xff); - block[j + 4] = (byte)((x[i] >> 24) & 0xff); - block[j + 5] = (byte)((x[i] >> 16) & 0xff); - block[j + 6] = (byte)((x[i] >> 8) & 0xff); - block[j + 7] = (byte)(x[i] & 0xff); - } - } } } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index e7c4bfaf1da3b..aa1e4bb91219c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -656,12 +656,15 @@ + - + + diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 49a19144a16b2..fd9701d7814b5 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -20,6 +20,7 @@ MONO_BIN_DIR?=$(BINDIR)/mono/Browser.wasm.$(CONFIG) NATIVE_BIN_DIR?=$(BINDIR)/native/net6.0-Browser-$(CONFIG)-wasm ICU_LIBDIR?= SYSTEM_NATIVE_LIBDIR?=$(TOP)/src/libraries/Native/Unix/System.Native +SYSTEM_CRYPTO_NATIVE_LIBDIR?=$(TOP)/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser ENABLE_ES6?=false _MSBUILD_WASM_BUILD_ARGS=/p:TargetOS=Browser /p:TargetArchitecture=wasm /p:Configuration=$(CONFIG) ENABLE_METADATA_UPDATE?=false @@ -60,6 +61,7 @@ MONO_LIBS = \ $(MONO_BIN_DIR)/libmono-profiler-aot.a \ ${NATIVE_BIN_DIR}/libSystem.Native.a \ ${NATIVE_BIN_DIR}/libSystem.IO.Compression.Native.a \ + ${NATIVE_BIN_DIR}/libSystem.Security.Cryptography.Native.Browser.a \ $(ICU_LIBDIR)/libicuuc.a \ $(ICU_LIBDIR)/libicui18n.a @@ -71,7 +73,7 @@ ifeq ($(ENABLE_METADATA_UPDATE),true) EMCC_FLAGS+=-DENABLE_METADATA_UPDATE=1 endif -EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DDEBUG=1 +EMCC_DEBUG_FLAGS =-g4 -Os -s ASSERTIONS=1 -DDEBUG=1 EMCC_RELEASE_FLAGS=-Oz --llvm-opts 2 ifeq ($(NOSTRIP),) @@ -101,8 +103,8 @@ $(NATIVE_BIN_DIR)/include/wasm: $(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 runtime/library_channel.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 --post-js runtime/library_channel.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 $(3) +$(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 runtime/library_channel.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.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 --post-js runtime/library_channel.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --js-library $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) $(BUILDS_OBJ_DIR)/pinvoke-table.h: $(PINVOKE_TABLE) | $(BUILDS_OBJ_DIR) if cmp -s $(PINVOKE_TABLE) $$@ ; then : ; else cp $(PINVOKE_TABLE) $$@ ; fi @@ -144,7 +146,7 @@ clean: icu-files: $(wildcard $(ICU_LIBDIR)/*.dat) $(ICU_LIBDIR)/libicuuc.a $(ICU_LIBDIR)/libicui18n.a | $(NATIVE_BIN_DIR) cp $^ $(NATIVE_BIN_DIR) -source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js | $(NATIVE_BIN_DIR)/src +source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.js | $(NATIVE_BIN_DIR)/src cp $^ $(NATIVE_BIN_DIR)/src header-files: runtime/pinvoke.h $(BUILDS_OBJ_DIR)/pinvoke-table.h | $(NATIVE_BIN_DIR)/include/wasm diff --git a/src/mono/wasm/runtime/crypto_worker.js b/src/mono/wasm/runtime/crypto_worker.js index 633ad842feada..b84374ce682d9 100644 --- a/src/mono/wasm/runtime/crypto_worker.js +++ b/src/mono/wasm/runtime/crypto_worker.js @@ -23,7 +23,7 @@ var ChannelWorker = { } async await_request(async_call) { - console.log("await_request()"); + // console.log("await_request()"); for (;;) { // Wait for signal to perform operation @@ -31,10 +31,16 @@ var ChannelWorker = { // Read in request var req = this._read_request(); - console.log("Request: " + req); + // console.log("Request: " + req); - // Perform async action based on request - var resp = await async_call(req); + var resp = null; + try { + // Perform async action based on request + resp = await async_call(req); + } + catch (err) { + resp = JSON.stringify(err); + } // Send response this._send_response(resp); @@ -117,32 +123,37 @@ var ChannelWorker = { } }; -// -// [TODO] Handle crypto calls that uses Promises below. -// +async function sha_hash(type, data) { + var sha_type = ""; + switch(type) { + case 0: sha_type = "SHA-1"; break; + case 1: sha_type = "SHA-256"; break; + case 2: sha_type = "SHA-384"; break; + case 3: sha_type = "SHA-512"; break; + default: + throw "CRYPTO: Unknown SHA: " + type; + } + + var digest = await crypto.subtle.digest(sha_type, data); + return Array.from(new Uint8Array(digest)); +} // Operation to perform. async function async_call(msg) { - var keyPair = await self.crypto.subtle.generateKey( - { - name: "RSA-OAEP", - modulusLength: 2048, - publicExponent: new Uint8Array([1, 0, 1]), - hash: "SHA-256", - }, - true, - ["encrypt", "decrypt"] - ); - - return msg.split("").reverse().join(""); + const req = JSON.parse(msg); + + if (req.func === "sha") { + var digestArr = await sha_hash(req.type, new Uint8Array(req.data)); + return JSON.stringify(digestArr); + } else { + throw "CRYPTO: Unknown request: " + req.func; + } } var s_channel; // Initialize WebWorker onmessage = function (p) { - console.log(p.data.salutation); s_channel = ChannelWorker.create(p.data.comm_buf, p.data.msg_buf, p.data.msg_char_len); - s_channel.await_request(async_call); } diff --git a/src/mono/wasm/runtime/library_channel.js b/src/mono/wasm/runtime/library_channel.js index 17e95d6a2e14b..6c4d89c912b8b 100644 --- a/src/mono/wasm/runtime/library_channel.js +++ b/src/mono/wasm/runtime/library_channel.js @@ -124,7 +124,6 @@ Module [ 'channel' ] = { _read_from_msg(begin, end) { return String.fromCharCode.apply(null, this.msg.slice(begin, end)); } - }, create: function (msg_char_len) { diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 42d73c6cfa17b..690adaf2d5ea5 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -42,6 +42,7 @@ + From 5ec3db7411ba8569a64778e4c8d8b858c282fb55 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Thu, 11 Mar 2021 13:42:58 -0800 Subject: [PATCH 04/23] Initialize WebWorker earlier. - Moved ChannelLib to be pre-js so worker init can happen earlier. Add function for WebWorker shutdown. This is needed to not deadlock test harness. Document where SubtleCrypto API was looked for in the v8 test harness. It was not found. --- .../pal_crypto_webworker.js | 2 +- src/mono/wasm/Makefile | 2 +- src/mono/wasm/runtime/crypto_worker.js | 22 ++++++++++++++++++- src/mono/wasm/runtime/library_channel.js | 12 ++++++++++ src/mono/wasm/runtime/library_mono.js | 18 ++++++++++----- 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js index c52f4af363568..13eeaaf772aad 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js @@ -12,7 +12,7 @@ var CryptoWebWorkerLib = { var response = MONO.mono_wasm_crypto.channel.send_msg(JSON.stringify(msg)); var digest = JSON.parse(response); if (digest.length !== output_len) { - throw "SHA HASH: Unexpected output length"; + throw "SHA HASH: Unexpected output length: " + digest.length + ", expected: " + output_len; } Module.HEAPU8.set(digest, output_buffer); diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index fd9701d7814b5..6165a5717233a 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -104,7 +104,7 @@ $(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 runtime/library_channel.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.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 --post-js runtime/library_channel.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --js-library $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) + $(EMCC) $(EMCC_FLAGS) $(1) --js-library runtime/library_mono.js --js-library runtime/binding_support.js --js-library runtime/dotnet_support.js --pre-js runtime/library_channel.js --js-library $(SYSTEM_NATIVE_LIBDIR)/pal_random.js --js-library $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.js $(BUILDS_OBJ_DIR)/driver.o $(BUILDS_OBJ_DIR)/pinvoke.o $(BUILDS_OBJ_DIR)/corebindings.o $(2) -o $(NATIVE_BIN_DIR)/dotnet.js $(3) $(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/crypto_worker.js b/src/mono/wasm/runtime/crypto_worker.js index b84374ce682d9..562fb03a45261 100644 --- a/src/mono/wasm/runtime/crypto_worker.js +++ b/src/mono/wasm/runtime/crypto_worker.js @@ -8,6 +8,7 @@ var ChannelWorker = { get MSG_SIZE_IDX() { return 1; } // Communication states. + get STATE_SHUTDOWN() { return -1; } // Shutdown get STATE_IDLE() { return 0; } get STATE_REQ() { return 1; } get STATE_RESP() { return 2; } @@ -32,6 +33,8 @@ var ChannelWorker = { // Read in request var req = this._read_request(); // console.log("Request: " + req); + if (req === this.STATE_SHUTDOWN) + break; var resp = null; try { @@ -39,6 +42,7 @@ var ChannelWorker = { resp = await async_call(req); } catch (err) { + console.log("Request error: " + err); resp = JSON.stringify(err); } @@ -61,6 +65,10 @@ var ChannelWorker = { if (state === this.STATE_REQ) break; + // Shutdown the worker. + if (state === this.STATE_SHUTDOWN) + return this.STATE_SHUTDOWN; + // Reset the size and transition to await state. Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); Atomics.store(this.comm, this.STATE_IDX, this.STATE_AWAIT); @@ -134,6 +142,14 @@ async function sha_hash(type, data) { throw "CRYPTO: Unknown SHA: " + type; } + // [TODO] The 'crypto' API is not available within the current + // v8 test harness. The following were tried: + // self + // document + // this + // globalThis + // + // The below works in the browser scenario. var digest = await crypto.subtle.digest(sha_type, data); return Array.from(new Uint8Array(digest)); } @@ -154,6 +170,10 @@ var s_channel; // Initialize WebWorker onmessage = function (p) { - s_channel = ChannelWorker.create(p.data.comm_buf, p.data.msg_buf, p.data.msg_char_len); + var data = p; + if (p.data !== undefined) { + data = p.data; + } + s_channel = ChannelWorker.create(data.comm_buf, data.msg_buf, data.msg_char_len); s_channel.await_request(async_call); } diff --git a/src/mono/wasm/runtime/library_channel.js b/src/mono/wasm/runtime/library_channel.js index 6c4d89c912b8b..8c028967568fd 100644 --- a/src/mono/wasm/runtime/library_channel.js +++ b/src/mono/wasm/runtime/library_channel.js @@ -9,6 +9,7 @@ Module [ 'channel' ] = { get COMM_LAST_IDX() { return this.MSG_SIZE_IDX; } // Communication states. + get STATE_SHUTDOWN() { return -1; } // Shutdown get STATE_IDLE() { return 0; } get STATE_REQ() { return 1; } get STATE_RESP() { return 2; } @@ -45,6 +46,17 @@ Module [ 'channel' ] = { return this._read_response(); } + shutdown() { + if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_IDLE) { + throw "OWNER: Invalid sync communication channel state."; + } + + // Notify webworker + Atomics.store(this.comm, this.MSG_SIZE_IDX, 0); + Atomics.store(this.comm, this.STATE_IDX, this.STATE_SHUTDOWN); + Atomics.notify(this.comm, this.STATE_IDX); + } + _send_request(msg) { var state; const msg_len = msg.length; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 29a76bb3ff0a4..dfd198e85213d 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -48,7 +48,7 @@ */ var MonoSupportLib = { - $MONO__postset: 'MONO.export_functions (Module);', + $MONO__postset: 'MONO.export_functions (Module); MONO._initialize_workers ();', $MONO: { pump_count: 0, timeout_queue: [], @@ -1707,7 +1707,6 @@ var MonoSupportLib = { var chan = Module.channel.create(); var worker = new Worker ("crypto_worker.js"); worker.postMessage ({ - salutation:"Message from main", comm_buf: chan.get_comm_buffer(), msg_buf: chan.get_msg_buffer(), msg_char_len: chan.get_msg_len() @@ -1716,6 +1715,14 @@ var MonoSupportLib = { MONO.mono_wasm_crypto.worker = worker; }, + _shutdown_workers: function () { + console.debug ("MONO_WASM: WebWorkers shutdown"); + var chan = MONO.mono_wasm_crypto.channel; + if (chan !== null) { + chan.shutdown (); + } + }, + _finalize_startup: function (args, ctx) { var loaded_files_with_debug_info = []; @@ -1753,12 +1760,11 @@ var MonoSupportLib = { tz = Intl.DateTimeFormat().resolvedOptions().timeZone; } catch {} MONO.mono_wasm_setenv ("TZ", tz || "UTC"); - - // Now that the runtime has been loaded, spin off any web workers needed - // for ancillary operations. - MONO._initialize_workers (); MONO.mono_wasm_runtime_ready (); args.loaded_cb (); + + // [TODO] Shutdown workers when run under test environment + // MONO._shutdown_workers(); }, _load_assets_and_runtime: function (args) { From c7e38880e9d4d0a2a671710e1b5094a86cae65c5 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Thu, 11 Mar 2021 14:07:44 -0800 Subject: [PATCH 05/23] Update logging and be less strict for output buffer size. --- .../pal_crypto_webworker.js | 4 ++-- src/mono/wasm/runtime/library_channel.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js index 13eeaaf772aad..b1ec349d2907c 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js @@ -11,8 +11,8 @@ var CryptoWebWorkerLib = { }; var response = MONO.mono_wasm_crypto.channel.send_msg(JSON.stringify(msg)); var digest = JSON.parse(response); - if (digest.length !== output_len) { - throw "SHA HASH: Unexpected output length: " + digest.length + ", expected: " + output_len; + if (digest.length > output_len) { + throw "SHA HASH: Digest length exceeds output length: " + digest.length + " > " + output_len; } Module.HEAPU8.set(digest, output_buffer); diff --git a/src/mono/wasm/runtime/library_channel.js b/src/mono/wasm/runtime/library_channel.js index 8c028967568fd..a2cf2b8cdb406 100644 --- a/src/mono/wasm/runtime/library_channel.js +++ b/src/mono/wasm/runtime/library_channel.js @@ -40,7 +40,7 @@ Module [ 'channel' ] = { send_msg(msg) { if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_IDLE) { - throw "OWNER: Invalid sync communication channel state."; + throw "OWNER: Invalid sync communication channel state. " + Atomics.load(this.comm, this.STATE_IDX); } this._send_request(msg); return this._read_response(); @@ -48,7 +48,7 @@ Module [ 'channel' ] = { shutdown() { if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_IDLE) { - throw "OWNER: Invalid sync communication channel state."; + throw "OWNER: Invalid sync communication channel state. " + Atomics.load(this.comm, this.STATE_IDX); } // Notify webworker From 47b5e6c0bd26e74c37c282dbf4b41e7ba5c12492 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Thu, 11 Mar 2021 14:30:49 -0800 Subject: [PATCH 06/23] Focus SHA tests for non-browser and browser DOM scenarios. --- .../Common/tests/TestUtilities/System/PlatformDetection.cs | 3 +++ .../tests/Sha1ManagedTests.cs | 1 + .../System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs | 1 + .../tests/Sha256ManagedTests.cs | 1 + .../tests/Sha256Tests.cs | 1 + .../tests/Sha384ManagedTests.cs | 1 + .../tests/Sha384Tests.cs | 1 + .../tests/Sha512ManagedTests.cs | 1 + .../tests/Sha512Tests.cs | 1 + 9 files changed, 11 insertions(+) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index f39ef807e9cab..7f9ee559354d3 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -61,6 +61,9 @@ public static partial class PlatformDetection public static bool IsUsingLimitedCultures => !IsNotMobile; public static bool IsNotUsingLimitedCultures => IsNotMobile; + public static bool IsPlatformCryptoSupported => !IsBrowser || IsBrowserDomSupported; + public static bool IsNotPlatformCryptoSupported => !IsPlatformCryptoSupported; + // Please make sure that you have the libgdiplus dependency installed. // For details, see https://docs.microsoft.com/dotnet/core/install/dependencies?pivots=os-macos&tabs=netcore31#libgdiplus public static bool IsDrawingSupported diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs index 5139841dcf829..27dd7bfed2233 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs @@ -6,6 +6,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests /// /// Sha1Managed has a copy of the same implementation as SHA1 /// + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha1ManagedTests : Sha1Tests { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs index 646d2dbb79801..575333b9ccf33 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs @@ -5,6 +5,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests { + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha1Tests : HashAlgorithmTest { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs index b1a0422272e86..dbebe4cc644d0 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs @@ -6,6 +6,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests /// /// Sha256Managed has a copy of the same implementation as SHA256 /// + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha256ManagedTests : Sha256Tests { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs index c53a7e83f299e..da799ea27f117 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs @@ -5,6 +5,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests { + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha256Tests : HashAlgorithmTest { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs index 42b13c63cd122..7c1985d597469 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs @@ -6,6 +6,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests /// /// Sha384Managed has a copy of the same implementation as SHA384 /// + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha384ManagedTests : Sha384Tests { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs index a0beb5d5faf1b..c0b6b15133378 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs @@ -5,6 +5,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests { + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha384Tests : HashAlgorithmTest { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs index b3fae310692c0..f45d06620643b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs @@ -6,6 +6,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests /// /// Sha512Managed has a copy of the same implementation as SHA512 /// + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha512ManagedTests : Sha512Tests { protected override HashAlgorithm Create() diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs index ef1d02fc818f7..71334f3f142d8 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs @@ -5,6 +5,7 @@ namespace System.Security.Cryptography.Hashing.Algorithms.Tests { + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public class Sha512Tests : HashAlgorithmTest { protected override HashAlgorithm Create() From d4ea7d6f7f16d0960f80b50697b3b9dccc3532c4 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Thu, 11 Mar 2021 16:04:08 -0800 Subject: [PATCH 07/23] Add missing namespaces to test builds. --- .../tests/Sha1ManagedTests.cs | 3 +++ .../System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs | 1 + .../tests/Sha256ManagedTests.cs | 3 +++ .../tests/Sha256Tests.cs | 1 + .../tests/Sha384ManagedTests.cs | 3 +++ .../tests/Sha384Tests.cs | 1 + .../tests/Sha512ManagedTests.cs | 3 +++ .../tests/Sha512Tests.cs | 1 + 8 files changed, 16 insertions(+) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs index 27dd7bfed2233..2a3d6b3b94232 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using Xunit; + namespace System.Security.Cryptography.Hashing.Algorithms.Tests { /// diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs index 575333b9ccf33..2b17b644de29b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Xunit; namespace System.Security.Cryptography.Hashing.Algorithms.Tests diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs index dbebe4cc644d0..4779f7b9eaac1 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using Xunit; + namespace System.Security.Cryptography.Hashing.Algorithms.Tests { /// diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs index da799ea27f117..6a53639003db8 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Xunit; namespace System.Security.Cryptography.Hashing.Algorithms.Tests diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs index 7c1985d597469..efaf85de6edb7 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using Xunit; + namespace System.Security.Cryptography.Hashing.Algorithms.Tests { /// diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs index c0b6b15133378..d2edea206dc2b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Xunit; namespace System.Security.Cryptography.Hashing.Algorithms.Tests diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs index f45d06620643b..0ef094644bb6c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using Xunit; + namespace System.Security.Cryptography.Hashing.Algorithms.Tests { /// diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs index 71334f3f142d8..53672a8734351 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using Xunit; namespace System.Security.Cryptography.Hashing.Algorithms.Tests From 8062a2f496fda4b9d0e6740e30f71a1244259a84 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Thu, 11 Mar 2021 19:31:29 -0800 Subject: [PATCH 08/23] Additional locations for that need the crypto_worker.js file. --- eng/liveBuilds.targets | 1 + src/mono/wasm/build/WasmApp.targets | 1 + 2 files changed, 2 insertions(+) diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index ade6e32134fb4..a4e59c84f2be4 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -163,6 +163,7 @@ $(LibrariesNativeArtifactsPath)dotnet.js; $(LibrariesNativeArtifactsPath)dotnet.wasm; $(LibrariesNativeArtifactsPath)dotnet.timezones.blat; + $(LibrariesNativeArtifactsPath)crypto_worker.js; $(LibrariesNativeArtifactsPath)*.dat;" IsNative="true" /> + From 2b38fddbaabda5be74164b9f694b3c4a579cb38d Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Fri, 12 Mar 2021 13:56:51 -0800 Subject: [PATCH 09/23] Add new JS and native binaries... everywhere. --- eng/SignCheckExclusionsFile.txt | 1 + .../pkg/sfx/Microsoft.NETCore.App/Directory.Build.props | 4 ++++ src/mono/wasm/Makefile | 2 +- src/mono/wasm/README.md | 3 +-- src/mono/wasm/build/WasmApp.targets | 5 ++++- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/eng/SignCheckExclusionsFile.txt b/eng/SignCheckExclusionsFile.txt index b45e2daaceb8d..62e8ad1964ae8 100644 --- a/eng/SignCheckExclusionsFile.txt +++ b/eng/SignCheckExclusionsFile.txt @@ -13,3 +13,4 @@ *comhosttemplatecomhostdll.dll;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549 *staticapphosttemplateapphostexe.exe;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549 *dotnet.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933 +*crypto_worker.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933 diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index 3de0a508d2005..8cadc00a04a14 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -91,6 +91,7 @@ + @@ -178,6 +179,7 @@ + @@ -187,7 +189,9 @@ + + diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 956bc439b9bf7..57842f158dff8 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -146,7 +146,7 @@ clean: icu-files: $(wildcard $(ICU_LIBDIR)/*.dat) $(ICU_LIBDIR)/libicuuc.a $(ICU_LIBDIR)/libicui18n.a | $(NATIVE_BIN_DIR) cp $^ $(NATIVE_BIN_DIR) -source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.js | $(NATIVE_BIN_DIR)/src +source-files: runtime/driver.c runtime/pinvoke.c runtime/corebindings.c runtime/binding_support.js runtime/dotnet_support.js runtime/library_mono.js runtime/library_channel.js $(SYSTEM_NATIVE_LIBDIR)/pal_random.js $(SYSTEM_CRYPTO_NATIVE_LIBDIR)/pal_crypto_webworker.js | $(NATIVE_BIN_DIR)/src cp $^ $(NATIVE_BIN_DIR)/src header-files: runtime/pinvoke.h $(BUILDS_OBJ_DIR)/pinvoke-table.h | $(NATIVE_BIN_DIR)/include/wasm diff --git a/src/mono/wasm/README.md b/src/mono/wasm/README.md index e4d7aa8b0271b..aa53de7424638 100644 --- a/src/mono/wasm/README.md +++ b/src/mono/wasm/README.md @@ -11,8 +11,7 @@ Note: Irrespective of `$(EMSDK_PATH)`'s value, `provision-wasm` will always inst `EMSDK_PATH` is set to `$reporoot/src/mono/wasm/emsdk` by default, by the Makefile. -Note: `EMSDK_PATH` is set by default in `src/mono/wasm/Makefile`, so building targets from that will have it set. But you might need to set it manually if -you are directly using the `dotnet build`, or `build.sh`. +Note: `EMSDK_PATH` is set by default in `src/mono/wasm/Makefile`, so building targets from that will have it set. But you might need to set it manually if you are directly using the `dotnet build`, or `build.sh`. ## Building diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 1670d02d6a76a..db239282e9a1d 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -291,6 +291,7 @@ <_WasmRuntimePackNativeLibs Include="libmono-icall-table.a"/> <_WasmRuntimePackNativeLibs Include="libSystem.Native.a"/> <_WasmRuntimePackNativeLibs Include="libSystem.IO.Compression.Native.a"/> + <_WasmRuntimePackNativeLibs Include="libSystem.Security.Cryptography.Native.Browser.a"/> <_WasmRuntimePackNativeLibs Include="libmono-profiler-aot.a"/> <_WasmRuntimePackNativeLibs Include="libicuuc.a" /> <_WasmRuntimePackNativeLibs Include="libicui18n.a" /> @@ -309,6 +310,8 @@ <_DotnetJSSrcFile Include="$(_WasmSrcDir)binding_support.js" /> <_DotnetJSSrcFile Include="$(_WasmSrcDir)dotnet_support.js" /> <_DotnetJSSrcFile Include="$(_WasmSrcDir)pal_random.js" /> + <_DotnetJSSrcFile Include="$(_WasmSrcDir)pal_crypto_webworker.js" /> + <_DotnetJSSrcPreFile Include="$(_WasmSrcDir)library_channel.js" /> <_AOTAssemblies Include="@(_WasmAssembliesInternal)" Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'" /> <_BitcodeFile Include="%(_WasmAssembliesInternal.LlvmBitcodeFile)" /> @@ -335,7 +338,7 @@ - + From 84dd60b989249874edf7c7db2a20044e5e05a245 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Fri, 12 Mar 2021 23:24:26 -0800 Subject: [PATCH 10/23] Reference the correct location for the webworker file. --- src/mono/wasm/build/WasmApp.targets | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index db239282e9a1d..8ed7ca640e2ef 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -265,6 +265,7 @@ <_WasmPInvokeModules Include="libSystem.Native" /> <_WasmPInvokeModules Include="libSystem.IO.Compression.Native" /> <_WasmPInvokeModules Include="libSystem.Globalization.Native" /> + <_WasmPInvokeModules Include="libSystem.Security.Cryptography.Native.Browser" /> - + From 36b2f56a15e6a105378fee8782b9464a3f0a0fae Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Sat, 13 Mar 2021 15:40:41 -0800 Subject: [PATCH 11/23] Specify the correct native directory path for the JS WebWorker file. --- src/mono/wasm/build/WasmApp.targets | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 8ed7ca640e2ef..f1c95563d5d7c 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -283,6 +283,9 @@ $(EmccFlags) -DLINK_ICALLS=1 <_WasmIncludeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include')) <_WasmSrcDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'src')) + + + <_WasmWebWorkerDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir))) @@ -345,7 +348,7 @@ - + From 80087a5e23cd7f7b1a775a02a0fbe870e4ad015c Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Sun, 14 Mar 2021 23:45:48 -0700 Subject: [PATCH 12/23] Only enable Crypto WebWorker when running in the browser scenario. --- src/mono/wasm/runtime/library_mono.js | 33 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 3a5a0a5979a5a..018289a539b62 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -1704,22 +1704,29 @@ var MonoSupportLib = { }, _initialize_workers: function () { - var chan = Module.channel.create(); - var worker = new Worker ("crypto_worker.js"); - worker.postMessage ({ - comm_buf: chan.get_comm_buffer(), - msg_buf: chan.get_msg_buffer(), - msg_char_len: chan.get_msg_len() - }); - MONO.mono_wasm_crypto.channel = chan; - MONO.mono_wasm_crypto.worker = worker; + console.debug ("MONO_WASM: Initialize WebWorkers"); + // Crypto support is only available in the Browser. + if (ENVIRONMENT_IS_WEB) { + var chan = Module.channel.create(); + var worker = new Worker ("crypto_worker.js"); + worker.postMessage ({ + comm_buf: chan.get_comm_buffer(), + msg_buf: chan.get_msg_buffer(), + msg_char_len: chan.get_msg_len() + }); + MONO.mono_wasm_crypto.channel = chan; + MONO.mono_wasm_crypto.worker = worker; + } }, _shutdown_workers: function () { - console.debug ("MONO_WASM: WebWorkers shutdown"); - var chan = MONO.mono_wasm_crypto.channel; - if (chan !== null) { - chan.shutdown (); + console.debug ("MONO_WASM: Shutdown WebWorkers"); + // Crypto support is only available in the Browser. + if (ENVIRONMENT_IS_WEB) { + var chan = MONO.mono_wasm_crypto.channel; + if (chan !== null) { + chan.shutdown (); + } } }, From 6a3b8a66186ad6b6760be3f720d14342b675e221 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Mon, 15 Mar 2021 10:25:13 -0700 Subject: [PATCH 13/23] Condition more tests based on platform Crypto support needed. --- .../tests/IncrementalHashTests.cs | 26 +++++++++---------- .../tests/InvalidUsageTests.cs | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs index b80efd70a8d2e..7a8e9a7e57174 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs @@ -68,7 +68,7 @@ public static void InvalidArguments_Throw() } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyIncrementalHash(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -142,7 +142,7 @@ private static void VerifyIncrementalResult(HashAlgorithm referenceAlgorithm, In Assert.Equal(referenceHash, incrementalB); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyEmptyHash(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -183,7 +183,7 @@ public static void VerifyEmptyHMAC(HMAC referenceAlgorithm, HashAlgorithmName ha } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyTrivialHash(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -214,7 +214,7 @@ public static void VerifyTrivialHMAC(HMAC referenceAlgorithm, HashAlgorithmName } } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public static void AppendDataAfterHashClose() { using (IncrementalHash hash = IncrementalHash.CreateHash(HashAlgorithmName.SHA256)) @@ -243,7 +243,7 @@ public static void AppendDataAfterHMACClose() } } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public static void GetHashTwice() { using (IncrementalHash hash = IncrementalHash.CreateHash(HashAlgorithmName.SHA256)) @@ -268,7 +268,7 @@ public static void GetHMACTwice() } } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public static void ModifyAfterHashDispose() { using (IncrementalHash hash = IncrementalHash.CreateHash(HashAlgorithmName.SHA256)) @@ -306,7 +306,7 @@ public static void UnknownHmacAlgorithm() () => IncrementalHash.CreateHMAC(new HashAlgorithmName("SHA0"), Array.Empty())); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyIncrementalHash_Span(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -374,7 +374,7 @@ private static void VerifyIncrementalResult_Span(HashAlgorithm referenceAlgorith Assert.Equal(new Span(referenceHash, 0, referenceHashLength).ToArray(), incrementalB); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyEmptyHash_Span(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -417,7 +417,7 @@ public static void VerifyEmptyHMAC_Span(HMAC referenceAlgorithm, HashAlgorithmNa } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyTrivialHash_Span(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -450,7 +450,7 @@ public static void VerifyTrivialHMAC_Span(HMAC referenceAlgorithm, HashAlgorithm } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void Dispose_HashAlgorithm_ThrowsException(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -497,7 +497,7 @@ public static void Dispose_HMAC_ThrowsException(HMAC referenceAlgorithm, HashAlg Assert.Throws(() => incrementalHash.TryGetCurrentHash(tmpDest, out int _)); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyGetCurrentHash_Digest(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -568,7 +568,7 @@ public static void VerifyBounds_GetHashAndReset_HMAC(HMAC referenceAlgorithm, Ha } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyBounds_GetCurrentHash_Hash(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { @@ -587,7 +587,7 @@ public static void VerifyBounds_GetCurrentHash_Hash(HashAlgorithm referenceAlgor } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyBounds_GetHashAndReset_Hash(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/InvalidUsageTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/InvalidUsageTests.cs index 2517780cc96b7..86b0dee83c5a4 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/InvalidUsageTests.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/InvalidUsageTests.cs @@ -23,7 +23,7 @@ public void InvalidHashCoreArgumentsFromDerivedType() } } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))] public void InvalidHashCoreArgumentsFromStream() { using (SHA1 sha1 = SHA1.Create()) From d78f0e235bc13d7f37b8cbfb400f3936156826d2 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Mon, 15 Mar 2021 10:42:31 -0700 Subject: [PATCH 14/23] Rename crypto_worker.js to dotnet_crypto_worker.js --- eng/SignCheckExclusionsFile.txt | 2 +- eng/liveBuilds.targets | 2 +- src/mono/wasm/Makefile | 6 +++--- src/mono/wasm/build/WasmApp.targets | 6 +++--- .../runtime/{crypto_worker.js => dotnet_crypto_worker.js} | 0 src/mono/wasm/runtime/library_mono.js | 2 +- src/mono/wasm/wasm.proj | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) rename src/mono/wasm/runtime/{crypto_worker.js => dotnet_crypto_worker.js} (100%) diff --git a/eng/SignCheckExclusionsFile.txt b/eng/SignCheckExclusionsFile.txt index 62e8ad1964ae8..8316fedacad43 100644 --- a/eng/SignCheckExclusionsFile.txt +++ b/eng/SignCheckExclusionsFile.txt @@ -13,4 +13,4 @@ *comhosttemplatecomhostdll.dll;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549 *staticapphosttemplateapphostexe.exe;;Template, DO-NOT-SIGN, https://github.com/dotnet/core-setup/pull/7549 *dotnet.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933 -*crypto_worker.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933 +*dotnet_crypto_worker.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933 diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets index a4e59c84f2be4..7d9a70e4e276b 100644 --- a/eng/liveBuilds.targets +++ b/eng/liveBuilds.targets @@ -163,7 +163,7 @@ $(LibrariesNativeArtifactsPath)dotnet.js; $(LibrariesNativeArtifactsPath)dotnet.wasm; $(LibrariesNativeArtifactsPath)dotnet.timezones.blat; - $(LibrariesNativeArtifactsPath)crypto_worker.js; + $(LibrariesNativeArtifactsPath)dotnet_crypto_worker.js; $(LibrariesNativeArtifactsPath)*.dat;" IsNative="true" /> $$@ @@ -127,7 +127,7 @@ $(NATIVE_BIN_DIR)/src/emcc-flags.txt: | $(NATIVE_BIN_DIR)/src Makefile $(NATIVE_BIN_DIR)/src/emcc-version.txt: $(EMSDK_PATH)/upstream/.emsdk_version | $(NATIVE_BIN_DIR)/src $(EMCC) --version | head -1 > $$@ -build-native: $(NATIVE_BIN_DIR)/dotnet.js $(NATIVE_BIN_DIR)/crypto_worker.js $(NATIVE_BIN_DIR)/src/emcc-flags.txt $(NATIVE_BIN_DIR)/src/emcc-version.txt +build-native: $(NATIVE_BIN_DIR)/dotnet.js $(NATIVE_BIN_DIR)/dotnet_crypto_worker.js $(NATIVE_BIN_DIR)/src/emcc-flags.txt $(NATIVE_BIN_DIR)/src/emcc-version.txt endef diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index f1c95563d5d7c..f0dc3b535993d 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -209,14 +209,14 @@ <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.wasm'">true <_HasDotnetJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.js'">true - <_HasCryptoWorkerJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'crypto_worker.js'">true + <_HasCryptoWorkerJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet_crypto_worker.js'">true - + @@ -348,7 +348,7 @@ - + diff --git a/src/mono/wasm/runtime/crypto_worker.js b/src/mono/wasm/runtime/dotnet_crypto_worker.js similarity index 100% rename from src/mono/wasm/runtime/crypto_worker.js rename to src/mono/wasm/runtime/dotnet_crypto_worker.js diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 018289a539b62..0e1d71b29cddb 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -1708,7 +1708,7 @@ var MonoSupportLib = { // Crypto support is only available in the Browser. if (ENVIRONMENT_IS_WEB) { var chan = Module.channel.create(); - var worker = new Worker ("crypto_worker.js"); + var worker = new Worker ("dotnet_crypto_worker.js"); worker.postMessage ({ comm_buf: chan.get_comm_buffer(), msg_buf: chan.get_msg_buffer(), diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 690adaf2d5ea5..36b447717e9f3 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -93,7 +93,7 @@ Date: Mon, 15 Mar 2021 12:42:51 -0700 Subject: [PATCH 15/23] Missing installer directory. --- .../pkg/sfx/Microsoft.NETCore.App/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index 8cadc00a04a14..66564d12242e3 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -179,7 +179,7 @@ - + From 7eb087db2f8a892da5347f918c16754598720ad4 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Mon, 15 Mar 2021 18:04:13 -0700 Subject: [PATCH 16/23] Style --- .../pal_crypto_webworker.js | 12 ++++++------ src/mono/wasm/runtime/library_mono.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js index b1ec349d2907c..2c63e7774e74c 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js @@ -3,24 +3,24 @@ var CryptoWebWorkerLib = { $CRYPTOWEBWORKER: { - call_sha_hash: function(sha_hash, input_buffer, input_len, output_buffer, output_len) { + call_sha_hash: function (sha_hash, input_buffer, input_len, output_buffer, output_len) { var msg = { func: "sha", type: sha_hash, - data: Array.from(Module.HEAPU8.subarray(input_buffer, input_buffer + input_len)) + data: Array.from(Module.HEAPU8.subarray (input_buffer, input_buffer + input_len)) }; - var response = MONO.mono_wasm_crypto.channel.send_msg(JSON.stringify(msg)); - var digest = JSON.parse(response); + var response = MONO.mono_wasm_crypto.channel.send_msg (JSON.stringify (msg)); + var digest = JSON.parse (response); if (digest.length > output_len) { throw "SHA HASH: Digest length exceeds output length: " + digest.length + " > " + output_len; } - Module.HEAPU8.set(digest, output_buffer); + Module.HEAPU8.set (digest, output_buffer); return 1; } }, dotnet_browser_sha_hash: function (sha_hash, input_buffer, input_len, output_buffer, output_len) { - return CRYPTOWEBWORKER.call_sha_hash(sha_hash, input_buffer, input_len, output_buffer, output_len); + return CRYPTOWEBWORKER.call_sha_hash (sha_hash, input_buffer, input_len, output_buffer, output_len); }, }; diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 0e1d71b29cddb..8d206072c0b16 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -1707,7 +1707,7 @@ var MonoSupportLib = { console.debug ("MONO_WASM: Initialize WebWorkers"); // Crypto support is only available in the Browser. if (ENVIRONMENT_IS_WEB) { - var chan = Module.channel.create(); + var chan = Module.channel.create (); var worker = new Worker ("dotnet_crypto_worker.js"); worker.postMessage ({ comm_buf: chan.get_comm_buffer(), From 925dcc09c755de66cd944e710b33124ca8673cde Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Tue, 16 Mar 2021 16:02:43 -0700 Subject: [PATCH 17/23] Change internal API name to use generic "digest" name instead of the current supported SHA family. --- ...SHAHash.cs => Interop.SimpleDigestHash.cs} | 8 ++--- .../pal_crypto_webworker.c | 10 +++---- .../pal_crypto_webworker.h | 14 ++++----- .../pal_crypto_webworker.js | 12 ++++---- .../Cryptography/SHAHashProvider.Browser.cs | 12 ++++---- ...em.Security.Cryptography.Algorithms.csproj | 4 +-- src/mono/wasm/runtime/dotnet_crypto_worker.js | 30 ++++++++----------- 7 files changed, 42 insertions(+), 48 deletions(-) rename src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/{Interop.SHAHash.cs => Interop.SimpleDigestHash.cs} (78%) diff --git a/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SimpleDigestHash.cs similarity index 78% rename from src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs rename to src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SimpleDigestHash.cs index f7e6756b7a3e4..a5e5a4765961b 100644 --- a/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SHAHash.cs +++ b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SimpleDigestHash.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class BrowserCrypto { - internal enum ShaHash + internal enum SimpleDigest { Sha1, Sha256, @@ -17,9 +17,9 @@ internal enum ShaHash Sha512, }; - [DllImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_SHAHash")] - internal static extern unsafe int SHAHash( - ShaHash hash, + [DllImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_SimpleDigestHash")] + internal static extern unsafe int SimpleDigestHash( + SimpleDigest hash, byte* input_buffer, int input_len, byte* output_buffer, diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c index 0ef32519500f5..50adb4d84af70 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.c @@ -5,19 +5,19 @@ #include "pal_crypto_webworker.h" // Forward declarations -extern int32_t dotnet_browser_sha_hash( - enum sha_hash ver, +extern int32_t dotnet_browser_simple_digest_hash( + enum simple_digest ver, uint8_t* input_buffer, int32_t input_len, uint8_t* output_buffer, int32_t output_len); -int32_t SystemCryptoNativeBrowser_SHAHash( - enum sha_hash ver, +int32_t SystemCryptoNativeBrowser_SimpleDigestHash( + enum simple_digest ver, uint8_t* input_buffer, int32_t input_len, uint8_t* output_buffer, int32_t output_len) { - return dotnet_browser_sha_hash(ver, input_buffer, input_len, output_buffer, output_len); + return dotnet_browser_simple_digest_hash(ver, input_buffer, input_len, output_buffer, output_len); } diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h index d60d3a3c067a9..93dae44653db6 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.h @@ -5,16 +5,16 @@ #include -enum sha_hash +enum simple_digest { - sha_hash_1, - sha_hash_256, - sha_hash_384, - sha_hash_512, + sd_sha_1, + sd_sha_256, + sd_sha_384, + sd_sha_512, }; -PALEXPORT int32_t SystemCryptoNativeBrowser_SHAHash( - enum sha_hash ver, +PALEXPORT int32_t SystemCryptoNativeBrowser_SimpleDigestHash( + enum simple_digest ver, uint8_t* input_buffer, int32_t input_len, uint8_t* output_buffer, diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js index 2c63e7774e74c..788ea467a7b6b 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js @@ -3,24 +3,24 @@ var CryptoWebWorkerLib = { $CRYPTOWEBWORKER: { - call_sha_hash: function (sha_hash, input_buffer, input_len, output_buffer, output_len) { + call_digest: function (hash, input_buffer, input_len, output_buffer, output_len) { var msg = { - func: "sha", - type: sha_hash, + func: "digest", + type: hash, data: Array.from(Module.HEAPU8.subarray (input_buffer, input_buffer + input_len)) }; var response = MONO.mono_wasm_crypto.channel.send_msg (JSON.stringify (msg)); var digest = JSON.parse (response); if (digest.length > output_len) { - throw "SHA HASH: Digest length exceeds output length: " + digest.length + " > " + output_len; + throw "DIGEST HASH: Digest length exceeds output length: " + digest.length + " > " + output_len; } Module.HEAPU8.set (digest, output_buffer); return 1; } }, - dotnet_browser_sha_hash: function (sha_hash, input_buffer, input_len, output_buffer, output_len) { - return CRYPTOWEBWORKER.call_sha_hash (sha_hash, input_buffer, input_len, output_buffer, output_len); + dotnet_browser_simple_digest_hash: function (hash, input_buffer, input_len, output_buffer, output_len) { + return CRYPTOWEBWORKER.call_digest (hash, input_buffer, input_len, output_buffer, output_len); }, }; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs index b3094a1cb0eba..d3c3ef4ff4a3e 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs @@ -12,7 +12,7 @@ namespace Internal.Cryptography internal sealed class SHAHashProvider : HashProvider { private readonly int hashSizeInBytes; - private readonly Interop.BrowserCrypto.ShaHash impl; + private readonly Interop.BrowserCrypto.SimpleDigest impl; private MemoryStream buffer; public SHAHashProvider(string hashAlgorithmId) @@ -20,19 +20,19 @@ public SHAHashProvider(string hashAlgorithmId) switch (hashAlgorithmId) { case HashAlgorithmNames.SHA1: - impl = Interop.BrowserCrypto.ShaHash.Sha1; + impl = Interop.BrowserCrypto.SimpleDigest.Sha1; hashSizeInBytes = 20; break; case HashAlgorithmNames.SHA256: - impl = Interop.BrowserCrypto.ShaHash.Sha256; + impl = Interop.BrowserCrypto.SimpleDigest.Sha256; hashSizeInBytes = 32; break; case HashAlgorithmNames.SHA384: - impl = Interop.BrowserCrypto.ShaHash.Sha384; + impl = Interop.BrowserCrypto.SimpleDigest.Sha384; hashSizeInBytes = 48; break; case HashAlgorithmNames.SHA512: - impl = Interop.BrowserCrypto.ShaHash.Sha512; + impl = Interop.BrowserCrypto.SimpleDigest.Sha512; hashSizeInBytes = 64; break; default: @@ -75,7 +75,7 @@ public override int GetCurrentHash(Span destination) fixed (byte* src = srcArray) fixed (byte* dest = destination) { - Interop.BrowserCrypto.SHAHash(impl, src, srcLength, dest, destination.Length); + Interop.BrowserCrypto.SimpleDigestHash(impl, src, srcLength, dest, destination.Length); } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index a796f1602cc4f..0592bb2e45a52 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -664,8 +664,8 @@ Link="Common\Interop\Browser\Interop.Libraries.cs" /> - + diff --git a/src/mono/wasm/runtime/dotnet_crypto_worker.js b/src/mono/wasm/runtime/dotnet_crypto_worker.js index 562fb03a45261..5ea07d2bfc09a 100644 --- a/src/mono/wasm/runtime/dotnet_crypto_worker.js +++ b/src/mono/wasm/runtime/dotnet_crypto_worker.js @@ -131,26 +131,20 @@ var ChannelWorker = { } }; -async function sha_hash(type, data) { - var sha_type = ""; +async function call_digest(type, data) { + var digest_type = ""; switch(type) { - case 0: sha_type = "SHA-1"; break; - case 1: sha_type = "SHA-256"; break; - case 2: sha_type = "SHA-384"; break; - case 3: sha_type = "SHA-512"; break; + case 0: digest_type = "SHA-1"; break; + case 1: digest_type = "SHA-256"; break; + case 2: digest_type = "SHA-384"; break; + case 3: digest_type = "SHA-512"; break; default: - throw "CRYPTO: Unknown SHA: " + type; + throw "CRYPTO: Unknown digest: " + type; } - // [TODO] The 'crypto' API is not available within the current - // v8 test harness. The following were tried: - // self - // document - // this - // globalThis - // - // The below works in the browser scenario. - var digest = await crypto.subtle.digest(sha_type, data); + // The 'crypto' API is not available in non-browser + // environments (for example, v8 server). + var digest = await crypto.subtle.digest(digest_type, data); return Array.from(new Uint8Array(digest)); } @@ -158,8 +152,8 @@ async function sha_hash(type, data) { async function async_call(msg) { const req = JSON.parse(msg); - if (req.func === "sha") { - var digestArr = await sha_hash(req.type, new Uint8Array(req.data)); + if (req.func === "digest") { + var digestArr = await call_digest(req.type, new Uint8Array(req.data)); return JSON.stringify(digestArr); } else { throw "CRYPTO: Unknown request: " + req.func; From 753c57b1dc1497cf72f2b146c80840cfe7272bcc Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Wed, 17 Mar 2021 13:38:40 -0700 Subject: [PATCH 18/23] Add test for not supported platform crypto WRT SHA --- .../pal_crypto_webworker.js | 4 +++ .../Cryptography/SHAHashProvider.Browser.cs | 6 +++- .../tests/ShaTests.NoPlatformCrypto.cs | 28 +++++++++++++++++++ ...urity.Cryptography.Algorithms.Tests.csproj | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/libraries/System.Security.Cryptography.Algorithms/tests/ShaTests.NoPlatformCrypto.cs diff --git a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js index 788ea467a7b6b..a617fc08182c1 100644 --- a/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js +++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js @@ -4,6 +4,10 @@ var CryptoWebWorkerLib = { $CRYPTOWEBWORKER: { call_digest: function (hash, input_buffer, input_len, output_buffer, output_len) { + if (MONO.mono_wasm_crypto.channel === null) { + return 0; // Not supported + } + var msg = { func: "digest", type: hash, diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs index d3c3ef4ff4a3e..ce590b6b87f75 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs @@ -75,7 +75,11 @@ public override int GetCurrentHash(Span destination) fixed (byte* src = srcArray) fixed (byte* dest = destination) { - Interop.BrowserCrypto.SimpleDigestHash(impl, src, srcLength, dest, destination.Length); + int res = Interop.BrowserCrypto.SimpleDigestHash(impl, src, srcLength, dest, destination.Length); + if (res == 0) + { + throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported); + } } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/ShaTests.NoPlatformCrypto.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/ShaTests.NoPlatformCrypto.cs new file mode 100644 index 0000000000000..4eb8e5a52ce22 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/ShaTests.NoPlatformCrypto.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using Xunit; + +namespace System.Security.Cryptography.Hashing.Algorithms.Tests +{ + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotPlatformCryptoSupported))] + public class ShaTests_NoPlatformCrypto + { + public static IEnumerable ShaImpl() + { + yield return new object[]{ SHA1.Create() }; + yield return new object[]{ SHA256.Create() }; + yield return new object[]{ SHA384.Create() }; + yield return new object[]{ SHA512.Create() }; + } + + [Theory] + [MemberData(nameof(ShaImpl))] + public void Sha_PlatformNotSupportedException(HashAlgorithm hash) + { + Assert.Throws(() => hash.ComputeHash(Array.Empty())); + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj b/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj index 4995d6690f944..08b43da8180db 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj @@ -245,6 +245,7 @@ + From b217fc4c2b1e2e5cfa8ce96880f955921fd4fed4 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 17 Mar 2021 15:47:24 -0700 Subject: [PATCH 19/23] Browser uses Unix binary builds so removing Windows placeholder. Removed unnecessary version source from Browser static lib build. --- .../CMakeLists.txt | 1 - src/libraries/Native/Windows/CMakeLists.txt | 4 ---- .../CMakeLists.txt | 0 3 files changed, 5 deletions(-) delete mode 100644 src/libraries/Native/Windows/System.Security.Cryptography.Native.Browser/CMakeLists.txt diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt index 46c346602d2ea..8005bbceadee1 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt @@ -10,7 +10,6 @@ set (NATIVE_SOURCES add_library (System.Security.Cryptography.Native.Browser-Static STATIC ${NATIVE_SOURCES} - ${VERSION_FILE_PATH} ) set_target_properties(System.Security.Cryptography.Native.Browser-Static PROPERTIES OUTPUT_NAME System.Security.Cryptography.Native.Browser CLEAN_DIRECT_OUTPUT 1) diff --git a/src/libraries/Native/Windows/CMakeLists.txt b/src/libraries/Native/Windows/CMakeLists.txt index c5b0594fe14ac..3f9924adb0a9d 100644 --- a/src/libraries/Native/Windows/CMakeLists.txt +++ b/src/libraries/Native/Windows/CMakeLists.txt @@ -130,7 +130,3 @@ if(STATIC_LIBS_ONLY) endif() add_subdirectory(System.IO.Compression.Native) - -if (CLR_CMAKE_TARGET_BROWSER) - add_subdirectory(System.SecurityCryptography.Native.Browser) -endif (CLR_CMAKE_TARGET_BROWSER) diff --git a/src/libraries/Native/Windows/System.Security.Cryptography.Native.Browser/CMakeLists.txt b/src/libraries/Native/Windows/System.Security.Cryptography.Native.Browser/CMakeLists.txt deleted file mode 100644 index e69de29bb2d1d..0000000000000 From a95e9d6787647a2019b4a66c40641932d15e87e2 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Wed, 17 Mar 2021 17:54:53 -0700 Subject: [PATCH 20/23] Add libSystem.Security.Cryptography.Native.Browser.a for Windows build. --- src/mono/wasm/wasm.proj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index d25d0e37ffcd7..6b9d1a61647b5 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -135,6 +135,7 @@ $(MonoArtifactsPath)libmono-icall-table.a; $(NativeBinDir)libSystem.Native.a; $(NativeBinDir)libSystem.IO.Compression.Native.a; + $(NativeBinDir)libSystem.Security.Cryptography.Native.Browser.a; $(ICULibDir)/libicuuc.a; $(ICULibDir)/libicui18n.a" /> From ce6d2b1bba3157c82c59cc166c6de74e8d8fa348 Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Wed, 17 Mar 2021 20:22:56 -0700 Subject: [PATCH 21/23] More Windows build changes. --- src/mono/wasm/wasm.proj | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 6b9d1a61647b5..ec86e3e760b7b 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -120,13 +120,14 @@ emcc --profiling-funcs -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s BINARYEN=1 -s ALIASING_FUNCTION_POINTERS=0 -s NO_EXIT_RUNTIME=1 -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'FS_createPath', 'FS_createDataFile', 'cwrap', 'setValue', 'getValue', 'UTF8ToString', 'UTF8ArrayToString', 'addFunction']" -s "EXPORTED_FUNCTIONS=['_putchar']" --source-map-base http://example.com -emit-llvm -s FORCE_FILESYSTEM=1 -s USE_ZLIB=1 $(EmccFlags) -s MODULARIZE=1 -s EXPORT_ES6=1 - -g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1 + -g4 -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1 -Oz --llvm-opts 2 -DENABLE_NETCORE=1 $(EMSDK_PATH)/upstream/bin/wasm-opt --strip-dwarf $(NativeBinDir)/dotnet.wasm -o $(NativeBinDir)/dotnet.wasm $(ArtifactsObjDir)wasm $(WasmObjDir)\emcc-version.txt $(MonoArtifactsPath)include/mono-2.0 $(RepoRoot)src\libraries\Native\Unix\System.Native + $(RepoRoot)src\libraries\Native\AnyOS\System.Security.Cryptography.Native.Browser - @@ -181,6 +182,11 @@ + + + @@ -207,7 +215,8 @@ From 742cbc32e64530b1a48d0928678af4568a5ba1a3 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Thu, 22 Apr 2021 15:05:22 -0500 Subject: [PATCH 22/23] Fix the js inclusion logic --- src/mono/wasm/build/WasmApp.targets | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index feabf866a66fc..eed57b36efc1b 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -386,9 +386,8 @@ <_DotnetJSSrcFile Include="$(_WasmRuntimePackSrcDir)\*.js" /> <_DotnetJSSrcPreFile Include="$(_WasmRuntimePackSrcDir)*channel.js" /> - <_DotnetJSSrcWokerFile Include="$(_WasmRuntimePackSrcDir)*webworker.js" /> - <_DotnetJSSrcFile Remove="@(_DotnetJSSrcPreFile);@(_DotnetJSSrcWokerFile)" /> + <_DotnetJSSrcFile Remove="@(_DotnetJSSrcPreFile)" /> <_AOTAssemblies Include="@(_WasmAssembliesInternal)" Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'" /> <_BitcodeFile Include="%(_WasmAssembliesInternal.LlvmBitcodeFile)" /> From 76dd72b428983f50580bf6d49f15ab4c055d6fad Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Thu, 22 Apr 2021 19:34:36 -0500 Subject: [PATCH 23/23] Add libSystem.Globalization.Native explicitly --- src/mono/wasm/build/WasmApp.targets | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index eed57b36efc1b..65943e75afeed 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -377,6 +377,9 @@ <_WasmRuntimePackNativeLibs Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\*.a"/> <_WasmPInvokeModules Include="@(_WasmRuntimePackSystemLibs->'%(FileName)')" /> + + <_WasmPInvokeModules Include="libSystem.Globalization.Native" /> + <_WasmObjectsToBuild Include="$(_WasmRuntimePackSrcDir)\*.c" /> <_WasmObjectsToBuild OutputPath="$(_WasmIntermediateOutputPath)%(FileName).o" />