Skip to content

Commit

Permalink
Better error handling in SubtleCrypto workers (#71693)
Browse files Browse the repository at this point in the history
* Better error handling in SubtleCrypto workers

Handle exceptions from SubtleCrypto by catching and logging exceptions coming from the crypto stack.

Reset web worker when a request fails.

Also, fix race conditions where the web worker can read its own response as part of the next request.

Contributes to #69740
  • Loading branch information
eerhardt authored Jul 7, 2022
1 parent 9610320 commit a2990b5
Show file tree
Hide file tree
Showing 7 changed files with 403 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,9 @@
<data name="Unknown_Error" xml:space="preserve">
<value>Unknown error.</value>
</data>
<data name="Unknown_SubtleCrypto_Error" xml:space="preserve">
<value>SubtleCrypto returned an unknown error: '{0}'.</value>
</data>
<data name="PlatformNotSupported_CipherModeBrowser" xml:space="preserve">
<value>Only CipherMode.CBC is supported on this platform.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ private unsafe int EncryptDecrypt(ReadOnlySpan<byte> input, Span<byte> output)
pOutput, output.Length);

if (bytesWritten < 0)
throw new Exception(SR.Unknown_Error);
throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, bytesWritten));

return bytesWritten;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,42 +43,35 @@ public override int GetCurrentHash(Span<byte> destination)
{
Debug.Assert(destination.Length >= _hashSizeInBytes);

byte[] srcArray = Array.Empty<byte>();
int srcLength = 0;
if (_buffer != null)
{
srcArray = _buffer.GetBuffer();
srcLength = (int)_buffer.Length;
}
ReadOnlySpan<byte> source = _buffer != null ?
new ReadOnlySpan<byte>(_buffer.GetBuffer(), 0, (int)_buffer.Length) :
default;

unsafe
{
fixed (byte* key = _key)
fixed (byte* src = srcArray)
fixed (byte* dest = destination)
{
int res = Interop.BrowserCrypto.Sign(_hashAlgorithm, key, _key.Length, src, srcLength, dest, destination.Length);
Debug.Assert(res != 0);
}
}
Sign(_hashAlgorithm, _key, source, destination);

return _hashSizeInBytes;
}

public static unsafe int MacDataOneShot(string hashAlgorithmId, ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> destination)
public static int MacDataOneShot(string hashAlgorithmId, ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> destination)
{
(SimpleDigest hashName, int hashSizeInBytes) = SHANativeHashProvider.HashAlgorithmToPal(hashAlgorithmId);
Debug.Assert(destination.Length >= hashSizeInBytes);

Sign(hashName, key, data, destination);

return hashSizeInBytes;
}

private static unsafe void Sign(SimpleDigest hashName, ReadOnlySpan<byte> key, ReadOnlySpan<byte> data, Span<byte> destination)
{
fixed (byte* k = key)
fixed (byte* src = data)
fixed (byte* dest = destination)
{
int res = Interop.BrowserCrypto.Sign(hashName, k, key.Length, src, data.Length, dest, destination.Length);
Debug.Assert(res != 0);
if (res != 0)
throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, res));
}

return hashSizeInBytes;
}

public override int HashSizeInBytes => _hashSizeInBytes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,40 +40,34 @@ public override int GetCurrentHash(Span<byte> destination)
{
Debug.Assert(destination.Length >= _hashSizeInBytes);

byte[] srcArray = Array.Empty<byte>();
int srcLength = 0;
if (_buffer != null)
{
srcArray = _buffer.GetBuffer();
srcLength = (int)_buffer.Length;
}
ReadOnlySpan<byte> source = _buffer != null ?
new ReadOnlySpan<byte>(_buffer.GetBuffer(), 0, (int)_buffer.Length) :
default;

unsafe
{
fixed (byte* src = srcArray)
fixed (byte* dest = destination)
{
int res = Interop.BrowserCrypto.SimpleDigestHash(_impl, src, srcLength, dest, destination.Length);
Debug.Assert(res != 0);
}
}
SimpleDigestHash(_impl, source, destination);

return _hashSizeInBytes;
}

public static unsafe int HashOneShot(string hashAlgorithmId, ReadOnlySpan<byte> data, Span<byte> destination)
public static int HashOneShot(string hashAlgorithmId, ReadOnlySpan<byte> data, Span<byte> destination)
{
(SimpleDigest impl, int hashSizeInBytes) = HashAlgorithmToPal(hashAlgorithmId);
Debug.Assert(destination.Length >= hashSizeInBytes);

SimpleDigestHash(impl, data, destination);

return hashSizeInBytes;
}

private static unsafe void SimpleDigestHash(SimpleDigest hashName, ReadOnlySpan<byte> data, Span<byte> destination)
{
fixed (byte* src = data)
fixed (byte* dest = destination)
{
int res = Interop.BrowserCrypto.SimpleDigestHash(impl, src, data.Length, dest, destination.Length);
Debug.Assert(res != 0);
int res = Interop.BrowserCrypto.SimpleDigestHash(hashName, src, data.Length, dest, destination.Length);
if (res != 0)
throw new CryptographicException(SR.Format(SR.Unknown_SubtleCrypto_Error, res));
}

return hashSizeInBytes;
}

public override int HashSizeInBytes => _hashSizeInBytes;
Expand Down
Loading

0 comments on commit a2990b5

Please sign in to comment.