Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/8.0-staging]: Add cryptographic operation counts to prevent process crashes #101737

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@
<data name="Cryptography_CipherModeNotSupported" xml:space="preserve">
<value>The specified CipherMode '{0}' is not supported.</value>
</data>
<data name="Cryptography_ConcurrentUseNotSupported" xml:space="preserve">
<value>Concurrent operations from multiple threads on this type are not supported.</value>
</data>
<data name="Cryptography_CngKeyWrongAlgorithm" xml:space="preserve">
<value>This key is for algorithm '{0}'. Expected '{1}'.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@
<Compile Include="System\Security\Cryptography\CapiHelper.Unix.cs" />
<Compile Include="System\Security\Cryptography\ChaCha20Poly1305.OpenSsl.cs" />
<Compile Include="System\Security\Cryptography\Cng.NotSupported.cs" />
<Compile Include="System\Security\Cryptography\ConcurrencyBlock.cs" />
<Compile Include="System\Security\Cryptography\CspKeyContainerInfo.NotSupported.cs" />
<Compile Include="System\Security\Cryptography\DESCryptoServiceProvider.Unix.cs" />
<Compile Include="System\Security\Cryptography\DesImplementation.OpenSsl.cs" />
Expand Down Expand Up @@ -977,6 +978,7 @@
<Compile Include="System\Security\Cryptography\CapiHelper.Shared.cs" />
<Compile Include="System\Security\Cryptography\CapiHelper.Unix.cs" />
<Compile Include="System\Security\Cryptography\Cng.NotSupported.cs" />
<Compile Include="System\Security\Cryptography\ConcurrencyBlock.NoOp.cs" />
<Compile Include="System\Security\Cryptography\CspKeyContainerInfo.NotSupported.cs" />
<Compile Include="System\Security\Cryptography\ChaCha20Poly1305.Android.cs" />
<Compile Include="System\Security\Cryptography\DESCryptoServiceProvider.Unix.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;

namespace System.Security.Cryptography
{
internal struct ConcurrencyBlock
{
internal static Scope Enter(ref ConcurrencyBlock block)
{
_ = block;
return default;
}

internal ref struct Scope
{
#pragma warning disable CA1822 // Member can be marked static
internal void Dispose()
{
}
#pragma warning restore CA1822
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;

namespace System.Security.Cryptography
{
internal struct ConcurrencyBlock
{
private int _count;

internal static Scope Enter(ref ConcurrencyBlock block)
{
int count = Interlocked.Increment(ref block._count);

if (count != 1)
{
Interlocked.Decrement(ref block._count);
throw new CryptographicException(SR.Cryptography_ConcurrentUseNotSupported);
}

return new Scope(ref block._count);
}

internal ref struct Scope
{
private ref int _parentCount;

internal Scope(ref int parentCount)
{
_parentCount = ref parentCount;
}

internal void Dispose()
{
Interlocked.Decrement(ref _parentCount);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ private sealed class EvpHashProvider : HashProvider
{
private readonly LiteHash _liteHash;
private bool _running;
private ConcurrencyBlock _block;

public EvpHashProvider(string hashAlgorithmId)
{
Expand All @@ -110,21 +111,30 @@ public EvpHashProvider(string hashAlgorithmId)

public override void AppendHashData(ReadOnlySpan<byte> data)
{
_liteHash.Append(data);
_running = true;
using (ConcurrencyBlock.Enter(ref _block))
{
_liteHash.Append(data);
_running = true;
}
}

public override int FinalizeHashAndReset(Span<byte> destination)
{
int written = _liteHash.Finalize(destination);
_liteHash.Reset();
_running = false;
return written;
using (ConcurrencyBlock.Enter(ref _block))
{
int written = _liteHash.Finalize(destination);
_liteHash.Reset();
_running = false;
return written;
}
}

public override int GetCurrentHash(Span<byte> destination)
{
return _liteHash.Current(destination);
using (ConcurrencyBlock.Enter(ref _block))
{
return _liteHash.Current(destination);
}
}

public override int HashSizeInBytes => _liteHash.HashSizeInBytes;
Expand All @@ -139,10 +149,13 @@ public override void Dispose(bool disposing)

public override void Reset()
{
if (_running)
using (ConcurrencyBlock.Enter(ref _block))
{
_liteHash.Reset();
_running = false;
if (_running)
{
_liteHash.Reset();
_running = false;
}
}
}
}
Expand All @@ -151,6 +164,7 @@ private sealed class HmacHashProvider : HashProvider
{
private readonly LiteHmac _liteHmac;
private bool _running;
private ConcurrencyBlock _block;

public HmacHashProvider(string hashAlgorithmId, ReadOnlySpan<byte> key)
{
Expand All @@ -159,21 +173,30 @@ public HmacHashProvider(string hashAlgorithmId, ReadOnlySpan<byte> key)

public override void AppendHashData(ReadOnlySpan<byte> data)
{
_liteHmac.Append(data);
_running = true;
using (ConcurrencyBlock.Enter(ref _block))
{
_liteHmac.Append(data);
_running = true;
}
}

public override int FinalizeHashAndReset(Span<byte> destination)
{
int written = _liteHmac.Finalize(destination);
_liteHmac.Reset();
_running = false;
return written;
using (ConcurrencyBlock.Enter(ref _block))
{
int written = _liteHmac.Finalize(destination);
_liteHmac.Reset();
_running = false;
return written;
}
}

public override int GetCurrentHash(Span<byte> destination)
{
return _liteHmac.Current(destination);
using (ConcurrencyBlock.Enter(ref _block))
{
return _liteHmac.Current(destination);
}
}

public override int HashSizeInBytes => _liteHmac.HashSizeInBytes;
Expand All @@ -188,10 +211,13 @@ public override void Dispose(bool disposing)

public override void Reset()
{
if (_running)
using (ConcurrencyBlock.Enter(ref _block))
{
_liteHmac.Reset();
_running = false;
if (_running)
{
_liteHmac.Reset();
_running = false;
}
}
}
}
Expand Down
Loading