Skip to content

Commit 70f5112

Browse files
authored
Add cryptographic operation counts to prevent process crashes
1 parent 4080420 commit 70f5112

File tree

5 files changed

+116
-20
lines changed

5 files changed

+116
-20
lines changed

src/libraries/System.Security.Cryptography/src/Resources/Strings.resx

+3
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@
273273
<data name="Cryptography_CipherModeNotSupported" xml:space="preserve">
274274
<value>The specified CipherMode '{0}' is not supported.</value>
275275
</data>
276+
<data name="Cryptography_ConcurrentUseNotSupported" xml:space="preserve">
277+
<value>Concurrent operations from multiple threads on this type are not supported.</value>
278+
</data>
276279
<data name="Cryptography_CngKeyWrongAlgorithm" xml:space="preserve">
277280
<value>This key is for algorithm '{0}'. Expected '{1}'.</value>
278281
</data>

src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@
817817
<Compile Include="System\Security\Cryptography\CapiHelper.Unix.cs" />
818818
<Compile Include="System\Security\Cryptography\ChaCha20Poly1305.OpenSsl.cs" />
819819
<Compile Include="System\Security\Cryptography\Cng.NotSupported.cs" />
820+
<Compile Include="System\Security\Cryptography\ConcurrencyBlock.cs" />
820821
<Compile Include="System\Security\Cryptography\CspKeyContainerInfo.NotSupported.cs" />
821822
<Compile Include="System\Security\Cryptography\DESCryptoServiceProvider.Unix.cs" />
822823
<Compile Include="System\Security\Cryptography\DesImplementation.OpenSsl.cs" />
@@ -977,6 +978,7 @@
977978
<Compile Include="System\Security\Cryptography\CapiHelper.Shared.cs" />
978979
<Compile Include="System\Security\Cryptography\CapiHelper.Unix.cs" />
979980
<Compile Include="System\Security\Cryptography\Cng.NotSupported.cs" />
981+
<Compile Include="System\Security\Cryptography\ConcurrencyBlock.NoOp.cs" />
980982
<Compile Include="System\Security\Cryptography\CspKeyContainerInfo.NotSupported.cs" />
981983
<Compile Include="System\Security\Cryptography\ChaCha20Poly1305.Android.cs" />
982984
<Compile Include="System\Security\Cryptography\DESCryptoServiceProvider.Unix.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Threading;
5+
6+
namespace System.Security.Cryptography
7+
{
8+
internal struct ConcurrencyBlock
9+
{
10+
internal static Scope Enter(ref ConcurrencyBlock block)
11+
{
12+
_ = block;
13+
return default;
14+
}
15+
16+
internal ref struct Scope
17+
{
18+
#pragma warning disable CA1822 // Member can be marked static
19+
internal void Dispose()
20+
{
21+
}
22+
#pragma warning restore CA1822
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Threading;
5+
6+
namespace System.Security.Cryptography
7+
{
8+
internal struct ConcurrencyBlock
9+
{
10+
private int _count;
11+
12+
internal static Scope Enter(ref ConcurrencyBlock block)
13+
{
14+
int count = Interlocked.Increment(ref block._count);
15+
16+
if (count != 1)
17+
{
18+
Interlocked.Decrement(ref block._count);
19+
throw new CryptographicException(SR.Cryptography_ConcurrentUseNotSupported);
20+
}
21+
22+
return new Scope(ref block._count);
23+
}
24+
25+
internal ref struct Scope
26+
{
27+
private ref int _parentCount;
28+
29+
internal Scope(ref int parentCount)
30+
{
31+
_parentCount = ref parentCount;
32+
}
33+
34+
internal void Dispose()
35+
{
36+
Interlocked.Decrement(ref _parentCount);
37+
}
38+
}
39+
}
40+
}

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs

+46-20
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ private sealed class EvpHashProvider : HashProvider
102102
{
103103
private readonly LiteHash _liteHash;
104104
private bool _running;
105+
private ConcurrencyBlock _block;
105106

106107
public EvpHashProvider(string hashAlgorithmId)
107108
{
@@ -110,21 +111,30 @@ public EvpHashProvider(string hashAlgorithmId)
110111

111112
public override void AppendHashData(ReadOnlySpan<byte> data)
112113
{
113-
_liteHash.Append(data);
114-
_running = true;
114+
using (ConcurrencyBlock.Enter(ref _block))
115+
{
116+
_liteHash.Append(data);
117+
_running = true;
118+
}
115119
}
116120

117121
public override int FinalizeHashAndReset(Span<byte> destination)
118122
{
119-
int written = _liteHash.Finalize(destination);
120-
_liteHash.Reset();
121-
_running = false;
122-
return written;
123+
using (ConcurrencyBlock.Enter(ref _block))
124+
{
125+
int written = _liteHash.Finalize(destination);
126+
_liteHash.Reset();
127+
_running = false;
128+
return written;
129+
}
123130
}
124131

125132
public override int GetCurrentHash(Span<byte> destination)
126133
{
127-
return _liteHash.Current(destination);
134+
using (ConcurrencyBlock.Enter(ref _block))
135+
{
136+
return _liteHash.Current(destination);
137+
}
128138
}
129139

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

140150
public override void Reset()
141151
{
142-
if (_running)
152+
using (ConcurrencyBlock.Enter(ref _block))
143153
{
144-
_liteHash.Reset();
145-
_running = false;
154+
if (_running)
155+
{
156+
_liteHash.Reset();
157+
_running = false;
158+
}
146159
}
147160
}
148161
}
@@ -151,6 +164,7 @@ private sealed class HmacHashProvider : HashProvider
151164
{
152165
private readonly LiteHmac _liteHmac;
153166
private bool _running;
167+
private ConcurrencyBlock _block;
154168

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

160174
public override void AppendHashData(ReadOnlySpan<byte> data)
161175
{
162-
_liteHmac.Append(data);
163-
_running = true;
176+
using (ConcurrencyBlock.Enter(ref _block))
177+
{
178+
_liteHmac.Append(data);
179+
_running = true;
180+
}
164181
}
165182

166183
public override int FinalizeHashAndReset(Span<byte> destination)
167184
{
168-
int written = _liteHmac.Finalize(destination);
169-
_liteHmac.Reset();
170-
_running = false;
171-
return written;
185+
using (ConcurrencyBlock.Enter(ref _block))
186+
{
187+
int written = _liteHmac.Finalize(destination);
188+
_liteHmac.Reset();
189+
_running = false;
190+
return written;
191+
}
172192
}
173193

174194
public override int GetCurrentHash(Span<byte> destination)
175195
{
176-
return _liteHmac.Current(destination);
196+
using (ConcurrencyBlock.Enter(ref _block))
197+
{
198+
return _liteHmac.Current(destination);
199+
}
177200
}
178201

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

189212
public override void Reset()
190213
{
191-
if (_running)
214+
using (ConcurrencyBlock.Enter(ref _block))
192215
{
193-
_liteHmac.Reset();
194-
_running = false;
216+
if (_running)
217+
{
218+
_liteHmac.Reset();
219+
_running = false;
220+
}
195221
}
196222
}
197223
}

0 commit comments

Comments
 (0)