#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) #pragma warning disable using System; using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters; namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes { /** * Implements a Gamming or Counter (CTR) mode on top of a DSTU 7624 block cipher. */ public class KCtrBlockCipher : IStreamCipher, IBlockCipher { private byte[] IV; private byte[] ofbV; private byte[] ofbOutV; private bool initialised; private int byteCount; private readonly int blockSize; private readonly IBlockCipher cipher; /** * Basic constructor. * * @param cipher the block cipher to be used as the basis of the * feedback mode. */ public KCtrBlockCipher(IBlockCipher cipher) { this.cipher = cipher; this.IV = new byte[cipher.GetBlockSize()]; this.blockSize = cipher.GetBlockSize(); this.ofbV = new byte[cipher.GetBlockSize()]; this.ofbOutV = new byte[cipher.GetBlockSize()]; } /** * return the underlying block cipher that we are wrapping. * * @return the underlying block cipher that we are wrapping. */ public IBlockCipher GetUnderlyingCipher() { return cipher; } /** * Initialise the cipher and, possibly, the initialisation vector (IV). * If an IV isn't passed as part of the parameter, the IV will be all zeros. * An IV which is too short is handled in FIPS compliant fashion. * * @param forEncryption if true the cipher is initialised for * encryption, if false for decryption. * @param param the key and other data required by the cipher. * @exception ArgumentException if the parameters argument is * inappropriate. */ public void Init( bool forEncryption, ICipherParameters parameters) { this.initialised = true; if (parameters is ParametersWithIV) { ParametersWithIV ivParam = (ParametersWithIV)parameters; byte[] iv = ivParam.GetIV(); int diff = IV.Length - iv.Length; Array.Clear(IV, 0, IV.Length); Array.Copy(iv, 0, IV, diff, iv.Length); parameters = ivParam.Parameters; } else { throw new ArgumentException("Invalid parameter passed"); } // if it's null, key is to be reused. if (parameters != null) { cipher.Init(true, parameters); } Reset(); } /** * return the algorithm name and mode. * * @return the name of the underlying algorithm followed by "/KCTR" * and the block size in bits. */ public string AlgorithmName { get { return cipher.AlgorithmName + "/KCTR"; } } public bool IsPartialBlockOkay { get { return true; } } /** * return the block size we are operating at. * * @return the block size we are operating at (in bytes). */ public int GetBlockSize() { return cipher.GetBlockSize(); } public byte ReturnByte(byte input) { return CalculateByte(input); } public void ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff) { if (outOff + len > output.Length) { throw new DataLengthException("Output buffer too short"); } if (inOff + len > input.Length) { throw new DataLengthException("Input buffer too small"); } int inStart = inOff; int inEnd = inOff + len; int outStart = outOff; while (inStart