| File: src\runtime\src\libraries\Common\src\System\Security\Cryptography\CryptoPool.cs | Web Access |
| Project: System.Security.Cryptography.csproj (System.Security.Cryptography) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; using System.Diagnostics; namespace System.Security.Cryptography { internal static class CryptoPool { internal const int ClearAll = -1; internal static byte[] Rent(int minimumLength) => ArrayPool<byte>.Shared.Rent(minimumLength); internal static void Return(ArraySegment<byte> arraySegment, int clearSize = ClearAll) { Debug.Assert(arraySegment.Array != null); Debug.Assert(arraySegment.Offset == 0); Return(arraySegment.Array, clearSize == ClearAll ? arraySegment.Count : clearSize); } internal static void Return(byte[] array, int clearSize = ClearAll) { Debug.Assert(clearSize <= array.Length); bool clearWholeArray = clearSize < 0; if (!clearWholeArray && clearSize != 0) { #if (NET || NETSTANDARD2_1) && !CP_NO_ZEROMEMORY CryptographicOperations.ZeroMemory(array.AsSpan(0, clearSize)); #else Array.Clear(array, 0, clearSize); #endif } ArrayPool<byte>.Shared.Return(array, clearWholeArray); } } internal ref struct CryptoPoolLease : IDisposable { private byte[]? _rented; private bool _skipClear; internal Span<byte> Span { get; private set; } internal readonly bool IsRented => _rented is not null; public void Dispose() { Return(); } internal void Return() { Return(_skipClear ? 0 : Span.Length); } private void Return(int clearSize) { if (_rented is not null) { CryptoPool.Return(_rented, clearSize); _rented = null; } else if (!_skipClear && clearSize > 0) { Span<byte> toClear = Span.Slice(0, clearSize); #if (NET || NETSTANDARD2_1) && !CP_NO_ZEROMEMORY CryptographicOperations.ZeroMemory(toClear); #else toClear.Clear(); #endif } Span = default; } internal static CryptoPoolLease Rent(int length, bool skipClear = false) { byte[] rented = CryptoPool.Rent(length); return new CryptoPoolLease { _rented = rented, _skipClear = skipClear, Span = new Span<byte>(rented, 0, length) }; } internal static CryptoPoolLease RentConditionally( int length, Span<byte> currentBuffer, bool skipClear = false, bool skipClearIfNotRented = false) { return RentConditionally( length, currentBuffer, out _, skipClear, skipClearIfNotRented); } internal static CryptoPoolLease RentConditionally( int length, Span<byte> currentBuffer, out bool rented, bool skipClear = false, bool skipClearIfNotRented = false) { if (currentBuffer.Length >= length) { rented = false; return new CryptoPoolLease { _rented = null, _skipClear = skipClearIfNotRented || skipClear, Span = currentBuffer.Slice(0, length) }; } rented = true; return Rent(length, skipClear); } } }