diff --git a/eng/SignCheckExclusionsFile.txt b/eng/SignCheckExclusionsFile.txt
index b45e2daaceb8d..8316fedacad43 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
+*dotnet_crypto_worker.js;;Workaround, https://github.com/dotnet/core-eng/issues/9933
diff --git a/eng/liveBuilds.targets b/eng/liveBuilds.targets
index 66da71ac53f75..117837a1676b5 100644
--- a/eng/liveBuilds.targets
+++ b/eng/liveBuilds.targets
@@ -169,6 +169,7 @@
$(LibrariesNativeArtifactsPath)dotnet.js;
$(LibrariesNativeArtifactsPath)dotnet.wasm;
$(LibrariesNativeArtifactsPath)dotnet.timezones.blat;
+ $(LibrariesNativeArtifactsPath)dotnet_crypto_worker.js;
$(LibrariesNativeArtifactsPath)*.dat;"
IsNative="true" />
+
@@ -201,6 +202,7 @@
+
@@ -210,7 +212,9 @@
+
+
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.SimpleDigestHash.cs b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SimpleDigestHash.cs
new file mode 100644
index 0000000000000..a5e5a4765961b
--- /dev/null
+++ b/src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.SimpleDigestHash.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 SimpleDigest
+ {
+ Sha1,
+ Sha256,
+ Sha384,
+ Sha512,
+ };
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "SystemCryptoNativeBrowser_SimpleDigestHash")]
+ internal static extern unsafe int SimpleDigestHash(
+ SimpleDigest hash,
+ byte* input_buffer,
+ int input_len,
+ byte* output_buffer,
+ int output_len);
+ }
+}
diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
index 34c4bb86c37de..261f49278a2d1 100644
--- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
+++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
@@ -62,6 +62,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/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..50adb4d84af70
--- /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_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_SimpleDigestHash(
+ enum simple_digest ver,
+ uint8_t* input_buffer,
+ int32_t input_len,
+ uint8_t* output_buffer,
+ int32_t 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
new file mode 100644
index 0000000000000..93dae44653db6
--- /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 simple_digest
+{
+ sd_sha_1,
+ sd_sha_256,
+ sd_sha_384,
+ sd_sha_512,
+};
+
+PALEXPORT int32_t SystemCryptoNativeBrowser_SimpleDigestHash(
+ enum simple_digest 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..a617fc08182c1
--- /dev/null
+++ b/src/libraries/Native/AnyOS/System.Security.Cryptography.Native.Browser/pal_crypto_webworker.js
@@ -0,0 +1,32 @@
+// 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_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,
+ 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 "DIGEST HASH: Digest length exceeds output length: " + digest.length + " > " + output_len;
+ }
+
+ Module.HEAPU8.set (digest, output_buffer);
+ return 1;
+ }
+ },
+ 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);
+ },
+};
+
+autoAddDeps(CryptoWebWorkerLib, '$CRYPTOWEBWORKER')
+mergeInto(LibraryManager.library, CryptoWebWorkerLib)
diff --git a/src/libraries/Native/Unix/CMakeLists.txt b/src/libraries/Native/Unix/CMakeLists.txt
index 8ebce76af457d..f95e7bccfcee2 100644
--- a/src/libraries/Native/Unix/CMakeLists.txt
+++ b/src/libraries/Native/Unix/CMakeLists.txt
@@ -251,7 +251,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..8005bbceadee1
--- /dev/null
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Browser/CMakeLists.txt
@@ -0,0 +1,17 @@
+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}
+)
+
+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/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs
index dff66e5ab8b61..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
@@ -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.SimpleDigest 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.SimpleDigest.Sha1;
hashSizeInBytes = 20;
break;
case HashAlgorithmNames.SHA256:
- impl = new SHA256ManagedImplementation();
+ impl = Interop.BrowserCrypto.SimpleDigest.Sha256;
hashSizeInBytes = 32;
break;
case HashAlgorithmNames.SHA384:
- impl = new SHA384ManagedImplementation();
+ impl = Interop.BrowserCrypto.SimpleDigest.Sha384;
hashSizeInBytes = 48;
break;
case HashAlgorithmNames.SHA512:
- impl = new SHA512ManagedImplementation();
+ impl = Interop.BrowserCrypto.SimpleDigest.Sha512;
hashSizeInBytes = 64;
break;
default:
@@ -62,965 +62,34 @@ 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 sealed 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 sealed 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()
+ unsafe
{
- 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)
- {
- 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)
+ int res = Interop.BrowserCrypto.SimpleDigestHash(impl, src, srcLength, dest, destination.Length);
+ if (res == 0)
{
- 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);
- }
- }
+ throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyAlgorithms_PlatformNotSupported);
}
}
}
- /* 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 sealed 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 sealed 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 static 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 6dbe4fe97575a..1b628074e716a 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
@@ -688,12 +688,15 @@
+
-
+
+
diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/IncrementalHashTests.cs
index 2a0f551c27903..df469cd68ad90 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 0adfe66cef73e..0e65a2d10a52e 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())
diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs
index 5139841dcf829..2a3d6b3b94232 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1ManagedTests.cs
@@ -1,11 +1,15 @@
// 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
{
///
/// 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..2b17b644de29b 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha1Tests.cs
@@ -1,10 +1,12 @@
// 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
{
+ [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..4779f7b9eaac1 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256ManagedTests.cs
@@ -1,11 +1,15 @@
// 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
{
///
/// 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..6a53639003db8 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha256Tests.cs
@@ -1,10 +1,12 @@
// 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
{
+ [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..efaf85de6edb7 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384ManagedTests.cs
@@ -1,11 +1,15 @@
// 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
{
///
/// 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..d2edea206dc2b 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha384Tests.cs
@@ -1,10 +1,12 @@
// 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
{
+ [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..0ef094644bb6c 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512ManagedTests.cs
@@ -1,11 +1,15 @@
// 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
{
///
/// 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..53672a8734351 100644
--- a/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs
+++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/Sha512Tests.cs
@@ -1,10 +1,12 @@
// 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
{
+ [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsPlatformCryptoSupported))]
public class Sha512Tests : HashAlgorithmTest
{
protected override HashAlgorithm Create()
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
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 abb93b97f4068..fba2f1d289954 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 $(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 $(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 --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
@@ -116,13 +118,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)/dotnet_crypto_worker.js: runtime/dotnet_crypto_worker.js | $(NATIVE_BIN_DIR)
+ cp runtime/dotnet_crypto_worker.js $(NATIVE_BIN_DIR)/dotnet_crypto_worker.js
+
$(NATIVE_BIN_DIR)/src/emcc-flags.txt: | $(NATIVE_BIN_DIR)/src Makefile
echo "$(call escape_quote,$(EMCC_FLAGS)) $(1)" > $$@
$(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)/dotnet_crypto_worker.js $(NATIVE_BIN_DIR)/src/emcc-flags.txt $(NATIVE_BIN_DIR)/src/emcc-version.txt
endef
@@ -141,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 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 | $(NATIVE_BIN_DIR)/include/wasm
diff --git a/src/mono/wasm/README.md b/src/mono/wasm/README.md
index 6a5dff401ab21..6cd66c9f94072 100644
--- a/src/mono/wasm/README.md
+++ b/src/mono/wasm/README.md
@@ -9,8 +9,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`.
* Alternatively you can install **correct version** yourself from the [Emscripten SDK guide](https://emscripten.org/docs/getting_started/downloads.html).
Do not install `latest` but rather specific version e.g. `./emsdk install 2.0.12`. See [emscripten-version.txt](./emscripten-version.txt)
diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets
index c5042c84080cb..7e9b7517e8c8f 100644
--- a/src/mono/wasm/build/WasmApp.targets
+++ b/src/mono/wasm/build/WasmApp.targets
@@ -322,12 +322,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)' == 'dotnet_crypto_worker.js'">true
+
@@ -376,13 +378,36 @@
$(EmccFlags) -g
$(EmccFlags) -DENABLE_AOT=1 -DDRIVER_GEN=1
$(EmccFlags) -DINVARIANT_GLOBALIZATION=1
+ <_WasmRuntimePackIncludeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include'))
+ <_WasmRuntimePackSrcDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'src'))
+
- <_WasmPInvokeModules Include="libSystem.Native" />
- <_WasmPInvokeModules Include="libSystem.IO.Compression.Native" />
- <_WasmPInvokeModules Include="libSystem.Globalization.Native" />
+ <_WasmRuntimePackSystemLibs Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\libSystem.*.a"/>
+ <_WasmRuntimePackNativeLibs Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\*.a"/>
+
+ <_WasmPInvokeModules Include="@(_WasmRuntimePackSystemLibs->'%(FileName)')" />
+
+ <_WasmPInvokeModules Include="libSystem.Globalization.Native" />
+
+ <_WasmObjectsToBuild Include="$(_WasmRuntimePackSrcDir)\*.c" />
+ <_WasmObjectsToBuild OutputPath="$(_WasmIntermediateOutputPath)%(FileName).o" />
+
+ <_WasmObjects Include="@(_WasmRuntimePackNativeLibs)" />
+ <_WasmObjects Include="@(_WasmObjectsToBuild->'%(OutputPath)')" />
+
+ <_DotnetJSSrcFile Include="$(_WasmRuntimePackSrcDir)\*.js" />
+
+ <_DotnetJSSrcPreFile Include="$(_WasmRuntimePackSrcDir)*channel.js" />
+
+ <_DotnetJSSrcFile Remove="@(_DotnetJSSrcPreFile)" />
+
+ <_AOTAssemblies Include="@(_WasmAssembliesInternal)" Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'" />
+ <_BitcodeFile Include="%(_WasmAssembliesInternal.LlvmBitcodeFile)" />
+
+
$(EmccFlags) -DLINK_ICALLS=1
<_WasmRuntimePackIncludeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include'))
<_WasmRuntimePackSrcDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'src'))
-
-
-
- <_WasmRuntimePackNativeLibs Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\*.a" />
- <_WasmObjectsToBuild Include="$(_WasmRuntimePackSrcDir)\*.c" />
- <_WasmObjectsToBuild OutputPath="$(_WasmIntermediateOutputPath)%(FileName).o" />
-
- <_WasmObjects Include="@(_WasmRuntimePackNativeLibs)" />
- <_WasmObjects Include="@(_WasmObjectsToBuild->'%(OutputPath)')" />
- <_DotnetJSSrcFile Include="$(_WasmRuntimePackSrcDir)\*.js" />
-
- <_AOTAssemblies Include="@(_WasmAssembliesInternal)" Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'" />
- <_BitcodeFile Include="%(_WasmAssembliesInternal.LlvmBitcodeFile)" />
-
+
+ <_WasmRuntimePackWebWorkerDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir)))
+
@@ -432,11 +446,13 @@
+
<_EmccLinkerArguments Include="$(EmccLDFlags)" />
<_EmccLinkerArguments Include="--js-library "%(_DotnetJSSrcFile.Identity)"" />
+ <_EmccLinkerArguments Include="--pre-js "%(_DotnetJSSrcPreFile.Identity)"" Condition="@(_DotNetJSSrcPreFile->Count()) > 0" />
<_EmccLinkerArguments Include=""%(_BitcodeFile.Identity)"" />
<_EmccLinkerArguments Include=""%(_WasmObjects.Identity)"" />
<_EmccLinkerArguments Include="-o "$(_WasmIntermediateOutputPath)dotnet.js"" />
@@ -455,6 +471,7 @@
+
diff --git a/src/mono/wasm/runtime/dotnet_crypto_worker.js b/src/mono/wasm/runtime/dotnet_crypto_worker.js
new file mode 100644
index 0000000000000..5ea07d2bfc09a
--- /dev/null
+++ b/src/mono/wasm/runtime/dotnet_crypto_worker.js
@@ -0,0 +1,173 @@
+// 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.
+ get STATE_IDX() { return 0; }
+ 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; }
+ 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) {
+ 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);
+ if (req === this.STATE_SHUTDOWN)
+ break;
+
+ var resp = null;
+ try {
+ // Perform async action based on request
+ resp = await async_call(req);
+ }
+ catch (err) {
+ console.log("Request error: " + err);
+ resp = JSON.stringify(err);
+ }
+
+ // 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;
+
+ // 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);
+ 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);
+ }
+};
+
+async function call_digest(type, data) {
+ var digest_type = "";
+ switch(type) {
+ 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 digest: " + type;
+ }
+
+ // 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));
+}
+
+// Operation to perform.
+async function async_call(msg) {
+ const req = JSON.parse(msg);
+
+ 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;
+ }
+}
+
+var s_channel;
+
+// Initialize WebWorker
+onmessage = function (p) {
+ 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
new file mode 100644
index 0000000000000..a2cf2b8cdb406
--- /dev/null
+++ b/src/mono/wasm/runtime/library_channel.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.
+
+Module [ 'channel' ] = {
+ _impl: class {
+ // Index constants for the communication buffer.
+ get STATE_IDX() { return 0; }
+ get MSG_SIZE_IDX() { return 1; }
+ 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; }
+ 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;
+
+ 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. " + Atomics.load(this.comm, this.STATE_IDX);
+ }
+ this._send_request(msg);
+ return this._read_response();
+ }
+
+ shutdown() {
+ if (Atomics.load(this.comm, this.STATE_IDX) !== this.STATE_IDLE) {
+ throw "OWNER: Invalid sync communication channel state. " + Atomics.load(this.comm, this.STATE_IDX);
+ }
+
+ // 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;
+ 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 685aaaf375d85..88223dd988495 100644
--- a/src/mono/wasm/runtime/library_mono.js
+++ b/src/mono/wasm/runtime/library_mono.js
@@ -48,13 +48,17 @@
*/
var MonoSupportLib = {
- $MONO__postset: 'MONO.export_functions (Module);',
+ $MONO__postset: 'MONO.export_functions (Module); MONO._initialize_workers ();',
$MONO: {
pump_count: 0,
timeout_queue: [],
_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: {},
@@ -1738,6 +1742,33 @@ var MonoSupportLib = {
return Module.ccall ('mono_wasm_get_icudt_name', 'string', ['string'], [culture]);
},
+ _initialize_workers: function () {
+ 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 ("dotnet_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: 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 ();
+ }
+ }
+ },
+
_finalize_startup: function (args, ctx) {
var loaded_files_with_debug_info = [];
@@ -1777,6 +1808,9 @@ var MonoSupportLib = {
MONO.mono_wasm_setenv ("TZ", tz || "UTC");
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) {
diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj
index dda6fa29f6272..4f461af81457b 100644
--- a/src/mono/wasm/wasm.proj
+++ b/src/mono/wasm/wasm.proj
@@ -44,6 +44,7 @@
+
@@ -91,6 +92,7 @@
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
+ $(NativeBinDir)libSystem.IO.Compression.Native.a;
+ $(NativeBinDir)libSystem.Security.Cryptography.Native.Browser.a" />
@@ -156,7 +160,7 @@
EmSdkPath="$(EMSDK_PATH)"
IgnoreStandardErrorWarningFormat="true" />
-
@@ -179,6 +183,11 @@
+
+
+
@@ -205,7 +216,8 @@