| File: System\Security\Cryptography\UniversalCryptoTransform.cs | Web Access |
| Project: src\runtime\src\libraries\System.Security.Cryptography\src\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; using System.Diagnostics; using System.Security.Cryptography; using Internal.Cryptography; namespace System.Security.Cryptography { // // The common base class for the cross-platform CreateEncryptor()/CreateDecryptor() implementations. // // - Implements the various padding algorithms (as we support padding algorithms that the underlying native apis don't.) // // - Parameterized by a BasicSymmetricCipher which encapsulates the algorithm, key, IV, chaining mode, direction of encryption // and the underlying native apis implementing the encryption. // internal abstract class UniversalCryptoTransform : ICryptoTransform { public static UniversalCryptoTransform Create( PaddingMode paddingMode, BasicSymmetricCipher cipher, bool encrypting) { if (encrypting) return new UniversalCryptoEncryptor(paddingMode, cipher); else return new UniversalCryptoDecryptor(paddingMode, cipher); } protected UniversalCryptoTransform(PaddingMode paddingMode, BasicSymmetricCipher basicSymmetricCipher) { PaddingMode = paddingMode; BasicSymmetricCipher = basicSymmetricCipher; } public bool CanReuseTransform { get { return true; } } public bool CanTransformMultipleBlocks { get { return true; } } protected int PaddingSizeBytes { get { return BasicSymmetricCipher.PaddingSizeInBytes; } } public int InputBlockSize { get { return BasicSymmetricCipher.BlockSizeInBytes; } } public int OutputBlockSize { get { return BasicSymmetricCipher.BlockSizeInBytes; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { ArgumentNullException.ThrowIfNull(inputBuffer); ArgumentOutOfRangeException.ThrowIfNegative(inputOffset); ArgumentOutOfRangeException.ThrowIfGreaterThan(inputOffset, inputBuffer.Length); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(inputCount); if (inputCount % InputBlockSize != 0) throw new ArgumentOutOfRangeException(nameof(inputCount), SR.Cryptography_MustTransformWholeBlock); if (inputCount > inputBuffer.Length - inputOffset) throw new ArgumentOutOfRangeException(nameof(inputCount), SR.Argument_InvalidOffLen); ArgumentNullException.ThrowIfNull(outputBuffer); ArgumentOutOfRangeException.ThrowIfGreaterThan(outputOffset, outputBuffer.Length); if (inputCount > outputBuffer.Length - outputOffset) throw new ArgumentOutOfRangeException(nameof(outputOffset), SR.Argument_InvalidOffLen); int numBytesWritten = UncheckedTransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset); Debug.Assert(numBytesWritten >= 0 && numBytesWritten <= inputCount); return numBytesWritten; } public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { ArgumentNullException.ThrowIfNull(inputBuffer); ArgumentOutOfRangeException.ThrowIfNegative(inputOffset); ArgumentOutOfRangeException.ThrowIfNegative(inputCount); ArgumentOutOfRangeException.ThrowIfGreaterThan(inputOffset, inputBuffer.Length); if (inputCount > inputBuffer.Length - inputOffset) throw new ArgumentOutOfRangeException(nameof(inputCount), SR.Argument_InvalidOffLen); byte[] output = UncheckedTransformFinalBlock(inputBuffer, inputOffset, inputCount); return output; } protected virtual void Dispose(bool disposing) { if (disposing) { BasicSymmetricCipher.Dispose(); } } protected int UncheckedTransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { return UncheckedTransformBlock(inputBuffer.AsSpan(inputOffset, inputCount), outputBuffer.AsSpan(outputOffset)); } protected abstract int UncheckedTransformBlock(ReadOnlySpan<byte> inputBuffer, Span<byte> outputBuffer); // For final block, encryption and decryption can give better context for the returning byte size, so we // don't provide an implementation here. protected abstract byte[] UncheckedTransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount); protected abstract int UncheckedTransformFinalBlock(ReadOnlySpan<byte> inputBuffer, Span<byte> outputBuffer); protected PaddingMode PaddingMode { get; } protected BasicSymmetricCipher BasicSymmetricCipher { get; } } }