summary refs log tree commit diff
path: root/Crypto/src/crypto/modes/SicBlockCipher.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/modes/SicBlockCipher.cs')
-rw-r--r--Crypto/src/crypto/modes/SicBlockCipher.cs110
1 files changed, 110 insertions, 0 deletions
diff --git a/Crypto/src/crypto/modes/SicBlockCipher.cs b/Crypto/src/crypto/modes/SicBlockCipher.cs
new file mode 100644
index 000000000..c45026e82
--- /dev/null
+++ b/Crypto/src/crypto/modes/SicBlockCipher.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+	/**
+	* Implements the Segmented Integer Counter (SIC) mode on top of a simple
+	* block cipher.
+	*/
+	public class SicBlockCipher
+		: IBlockCipher
+	{
+		private readonly IBlockCipher cipher;
+		private readonly int blockSize;
+		private readonly byte[] IV;
+		private readonly byte[] counter;
+		private readonly byte[] counterOut;
+
+		/**
+		* Basic constructor.
+		*
+		* @param c the block cipher to be used.
+		*/
+		public SicBlockCipher(IBlockCipher cipher)
+		{
+			this.cipher = cipher;
+			this.blockSize = cipher.GetBlockSize();
+			this.IV = new byte[blockSize];
+			this.counter = new byte[blockSize];
+			this.counterOut = new byte[blockSize];
+		}
+
+		/**
+		* return the underlying block cipher that we are wrapping.
+		*
+		* @return the underlying block cipher that we are wrapping.
+		*/
+		public IBlockCipher GetUnderlyingCipher()
+		{
+			return cipher;
+		}
+
+		public void Init(
+			bool				forEncryption, //ignored by this CTR mode
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithIV)
+			{
+				ParametersWithIV ivParam = (ParametersWithIV) parameters;
+				byte[] iv = ivParam.GetIV();
+				Array.Copy(iv, 0, IV, 0, IV.Length);
+
+				Reset();
+				cipher.Init(true, ivParam.Parameters);
+			}
+	        else
+	        {
+	            throw new ArgumentException("SIC mode requires ParametersWithIV", "parameters");
+	        }
+		}
+
+		public string AlgorithmName
+		{
+			get { return cipher.AlgorithmName + "/SIC"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		public int GetBlockSize()
+		{
+			return cipher.GetBlockSize();
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			cipher.ProcessBlock(counter, 0, counterOut, 0);
+
+			//
+			// XOR the counterOut with the plaintext producing the cipher text
+			//
+			for (int i = 0; i < counterOut.Length; i++)
+			{
+				output[outOff + i] = (byte)(counterOut[i] ^ input[inOff + i]);
+			}
+
+			// Increment the counter
+			int j = counter.Length;
+			while (--j >= 0 && ++counter[j] == 0)
+			{
+			}
+
+			return counter.Length;
+		}
+
+		public void Reset()
+		{
+			Array.Copy(IV, 0, counter, 0, counter.Length);
+			cipher.Reset();
+		}
+	}
+}