summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2013-07-07 07:16:28 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2013-07-07 07:16:28 +0700
commitc2ee11dea6e2e044479185b81730bda06c244407 (patch)
tree7abfb37491ad9a5f15028da69f45ebb4b33047d2
parentFix Platform references in tests (diff)
downloadBouncyCastle.NET-ed25519-c2ee11dea6e2e044479185b81730bda06c244407.tar.xz
Guard against passing IV thru CMac
-rw-r--r--crypto/src/crypto/macs/CMac.cs446
-rw-r--r--crypto/test/src/crypto/test/CMacTest.cs412
2 files changed, 440 insertions, 418 deletions
diff --git a/crypto/src/crypto/macs/CMac.cs b/crypto/src/crypto/macs/CMac.cs
index c51a550c9..997145a4d 100644
--- a/crypto/src/crypto/macs/CMac.cs
+++ b/crypto/src/crypto/macs/CMac.cs
@@ -2,129 +2,130 @@ using System;
 
 using Org.BouncyCastle.Crypto.Modes;
 using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
 
 namespace Org.BouncyCastle.Crypto.Macs
 {
-	/**
-	* CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
-	* <p>
-	* CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
-	* </p><p>
-	* CMAC is a NIST recomendation - see 
-	* csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
-	* </p><p>
-	* CMAC/OMAC1 is a blockcipher-based message authentication code designed and
-	* analyzed by Tetsu Iwata and Kaoru Kurosawa.
-	* </p><p>
-	* CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message 
-	* Authentication Code). OMAC stands for One-Key CBC MAC.
-	* </p><p>
-	* It supports 128- or 64-bits block ciphers, with any key size, and returns
-	* a MAC with dimension less or equal to the block size of the underlying 
-	* cipher.
-	* </p>
-	*/
-	public class CMac
-		: IMac
-	{
-		private const byte CONSTANT_128 = (byte)0x87;
-		private const byte CONSTANT_64 = (byte)0x1b;
-
-		private byte[] ZEROES;
-
-		private byte[] mac;
-
-		private byte[] buf;
-		private int bufOff;
-		private IBlockCipher cipher;
-
-		private int macSize;
-
-		private byte[] L, Lu, Lu2;
-
-		/**
-		* create a standard MAC based on a CBC block cipher (64 or 128 bit block).
-		* This will produce an authentication code the length of the block size
-		* of the cipher.
-		*
-		* @param cipher the cipher to be used as the basis of the MAC generation.
-		*/
-		public CMac(
-			IBlockCipher cipher)
-			: this(cipher, cipher.GetBlockSize() * 8)
-		{
-		}
-
-		/**
-		* create a standard MAC based on a block cipher with the size of the
-		* MAC been given in bits.
-		* <p/>
-		* Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
-		* or 16 bits if being used as a data authenticator (FIPS Publication 113),
-		* and in general should be less than the size of the block cipher as it reduces
-		* the chance of an exhaustive attack (see Handbook of Applied Cryptography).
-		*
-		* @param cipher        the cipher to be used as the basis of the MAC generation.
-		* @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and @lt;= 128.
-		*/
-		public CMac(
-			IBlockCipher	cipher,
-			int				macSizeInBits)
-		{
-			if ((macSizeInBits % 8) != 0)
-				throw new ArgumentException("MAC size must be multiple of 8");
-
-			if (macSizeInBits > (cipher.GetBlockSize() * 8))
-			{
-				throw new ArgumentException(
-					"MAC size must be less or equal to "
-						+ (cipher.GetBlockSize() * 8));
-			}
-
-			if (cipher.GetBlockSize() != 8 && cipher.GetBlockSize() != 16)
-			{
-				throw new ArgumentException(
-					"Block size must be either 64 or 128 bits");
-			}
-
-			this.cipher = new CbcBlockCipher(cipher);
-			this.macSize = macSizeInBits / 8;
-
-			mac = new byte[cipher.GetBlockSize()];
-
-			buf = new byte[cipher.GetBlockSize()];
-
-			ZEROES = new byte[cipher.GetBlockSize()];
-
-			bufOff = 0;
-		}
-
-		public string AlgorithmName
-		{
-			get { return cipher.AlgorithmName; }
-		}
-
-		private static byte[] doubleLu(
-			byte[] inBytes)
-		{
-			int FirstBit = (inBytes[0] & 0xFF) >> 7;
-			byte[] ret = new byte[inBytes.Length];
-			for (int i = 0; i < inBytes.Length - 1; i++)
-			{
-				ret[i] = (byte)((inBytes[i] << 1) + ((inBytes[i + 1] & 0xFF) >> 7));
-			}
-			ret[inBytes.Length - 1] = (byte)(inBytes[inBytes.Length - 1] << 1);
-			if (FirstBit == 1)
-			{
-				ret[inBytes.Length - 1] ^= inBytes.Length == 16 ? CONSTANT_128 : CONSTANT_64;
-			}
-			return ret;
-		}
-
-		public void Init(
-			ICipherParameters parameters)
-		{
-            if (parameters != null)
+    /**
+    * CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
+    * <p>
+    * CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
+    * </p><p>
+    * CMAC is a NIST recomendation - see 
+    * csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+    * </p><p>
+    * CMAC/OMAC1 is a blockcipher-based message authentication code designed and
+    * analyzed by Tetsu Iwata and Kaoru Kurosawa.
+    * </p><p>
+    * CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message 
+    * Authentication Code). OMAC stands for One-Key CBC MAC.
+    * </p><p>
+    * It supports 128- or 64-bits block ciphers, with any key size, and returns
+    * a MAC with dimension less or equal to the block size of the underlying 
+    * cipher.
+    * </p>
+    */
+    public class CMac
+        : IMac
+    {
+        private const byte CONSTANT_128 = (byte)0x87;
+        private const byte CONSTANT_64 = (byte)0x1b;
+
+        private byte[] ZEROES;
+
+        private byte[] mac;
+
+        private byte[] buf;
+        private int bufOff;
+        private IBlockCipher cipher;
+
+        private int macSize;
+
+        private byte[] L, Lu, Lu2;
+
+        /**
+        * create a standard MAC based on a CBC block cipher (64 or 128 bit block).
+        * This will produce an authentication code the length of the block size
+        * of the cipher.
+        *
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        */
+        public CMac(
+            IBlockCipher cipher)
+            : this(cipher, cipher.GetBlockSize() * 8)
+        {
+        }
+
+        /**
+        * create a standard MAC based on a block cipher with the size of the
+        * MAC been given in bits.
+        * <p/>
+        * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+        * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+        * and in general should be less than the size of the block cipher as it reduces
+        * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+        *
+        * @param cipher        the cipher to be used as the basis of the MAC generation.
+        * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and @lt;= 128.
+        */
+        public CMac(
+            IBlockCipher	cipher,
+            int				macSizeInBits)
+        {
+            if ((macSizeInBits % 8) != 0)
+                throw new ArgumentException("MAC size must be multiple of 8");
+
+            if (macSizeInBits > (cipher.GetBlockSize() * 8))
+            {
+                throw new ArgumentException(
+                    "MAC size must be less or equal to "
+                        + (cipher.GetBlockSize() * 8));
+            }
+
+            if (cipher.GetBlockSize() != 8 && cipher.GetBlockSize() != 16)
+            {
+                throw new ArgumentException(
+                    "Block size must be either 64 or 128 bits");
+            }
+
+            this.cipher = new CbcBlockCipher(cipher);
+            this.macSize = macSizeInBits / 8;
+
+            mac = new byte[cipher.GetBlockSize()];
+
+            buf = new byte[cipher.GetBlockSize()];
+
+            ZEROES = new byte[cipher.GetBlockSize()];
+
+            bufOff = 0;
+        }
+
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName; }
+        }
+
+        private static byte[] doubleLu(
+            byte[] inBytes)
+        {
+            int FirstBit = (inBytes[0] & 0xFF) >> 7;
+            byte[] ret = new byte[inBytes.Length];
+            for (int i = 0; i < inBytes.Length - 1; i++)
+            {
+                ret[i] = (byte)((inBytes[i] << 1) + ((inBytes[i + 1] & 0xFF) >> 7));
+            }
+            ret[inBytes.Length - 1] = (byte)(inBytes[inBytes.Length - 1] << 1);
+            if (FirstBit == 1)
+            {
+                ret[inBytes.Length - 1] ^= inBytes.Length == 16 ? CONSTANT_128 : CONSTANT_64;
+            }
+            return ret;
+        }
+
+        public void Init(
+            ICipherParameters parameters)
+        {
+            if (parameters is KeyParameter)
             {
                 cipher.Init(true, parameters);
 
@@ -134,108 +135,113 @@ namespace Org.BouncyCastle.Crypto.Macs
                 Lu = doubleLu(L);
                 Lu2 = doubleLu(Lu);
             }
+            else if (parameters != null)
+            {
+                // CMAC mode does not permit IV to underlying CBC mode
+                throw new ArgumentException("CMac mode only permits key to be set.", "parameters");
+            }
 
             Reset();
-		}
+        }
 
         public int GetMacSize()
-		{
-			return macSize;
-		}
-
-		public void Update(
-			byte input)
-		{
-			if (bufOff == buf.Length)
-			{
-				cipher.ProcessBlock(buf, 0, mac, 0);
-				bufOff = 0;
-			}
-
-			buf[bufOff++] = input;
-		}
-
-		public void BlockUpdate(
-			byte[]	inBytes,
-			int		inOff,
-			int		len)
-		{
-			if (len < 0)
-				throw new ArgumentException("Can't have a negative input length!");
-
-			int blockSize = cipher.GetBlockSize();
-			int gapLen = blockSize - bufOff;
-
-			if (len > gapLen)
-			{
-				Array.Copy(inBytes, inOff, buf, bufOff, gapLen);
-
-				cipher.ProcessBlock(buf, 0, mac, 0);
-
-				bufOff = 0;
-				len -= gapLen;
-				inOff += gapLen;
-
-				while (len > blockSize)
-				{
-					cipher.ProcessBlock(inBytes, inOff, mac, 0);
-
-					len -= blockSize;
-					inOff += blockSize;
-				}
-			}
-
-			Array.Copy(inBytes, inOff, buf, bufOff, len);
-
-			bufOff += len;
-		}
-
-		public int DoFinal(
-			byte[]	outBytes,
-			int		outOff)
-		{
-			int blockSize = cipher.GetBlockSize();
-
-			byte[] lu;
-			if (bufOff == blockSize)
-			{
-				lu = Lu;
-			}
-			else
-			{
-				new ISO7816d4Padding().AddPadding(buf, bufOff);
-				lu = Lu2;
-			}
-
-			for (int i = 0; i < mac.Length; i++)
-			{
-				buf[i] ^= lu[i];
-			}
-
-			cipher.ProcessBlock(buf, 0, mac, 0);
-
-			Array.Copy(mac, 0, outBytes, outOff, macSize);
-
-			Reset();
-
-			return macSize;
-		}
-
-		/**
-		* Reset the mac generator.
-		*/
-		public void Reset()
-		{
-			/*
-			* clean the buffer.
-			*/
-			Array.Clear(buf, 0, buf.Length);
-			bufOff = 0;
-
-			/*
-			* Reset the underlying cipher.
-			*/
-			cipher.Reset();
-		}
-	}
+        {
+            return macSize;
+        }
+
+        public void Update(
+            byte input)
+        {
+            if (bufOff == buf.Length)
+            {
+                cipher.ProcessBlock(buf, 0, mac, 0);
+                bufOff = 0;
+            }
+
+            buf[bufOff++] = input;
+        }
+
+        public void BlockUpdate(
+            byte[]	inBytes,
+            int		inOff,
+            int		len)
+        {
+            if (len < 0)
+                throw new ArgumentException("Can't have a negative input length!");
+
+            int blockSize = cipher.GetBlockSize();
+            int gapLen = blockSize - bufOff;
+
+            if (len > gapLen)
+            {
+                Array.Copy(inBytes, inOff, buf, bufOff, gapLen);
+
+                cipher.ProcessBlock(buf, 0, mac, 0);
+
+                bufOff = 0;
+                len -= gapLen;
+                inOff += gapLen;
+
+                while (len > blockSize)
+                {
+                    cipher.ProcessBlock(inBytes, inOff, mac, 0);
+
+                    len -= blockSize;
+                    inOff += blockSize;
+                }
+            }
+
+            Array.Copy(inBytes, inOff, buf, bufOff, len);
+
+            bufOff += len;
+        }
+
+        public int DoFinal(
+            byte[]	outBytes,
+            int		outOff)
+        {
+            int blockSize = cipher.GetBlockSize();
+
+            byte[] lu;
+            if (bufOff == blockSize)
+            {
+                lu = Lu;
+            }
+            else
+            {
+                new ISO7816d4Padding().AddPadding(buf, bufOff);
+                lu = Lu2;
+            }
+
+            for (int i = 0; i < mac.Length; i++)
+            {
+                buf[i] ^= lu[i];
+            }
+
+            cipher.ProcessBlock(buf, 0, mac, 0);
+
+            Array.Copy(mac, 0, outBytes, outOff, macSize);
+
+            Reset();
+
+            return macSize;
+        }
+
+        /**
+        * Reset the mac generator.
+        */
+        public void Reset()
+        {
+            /*
+            * clean the buffer.
+            */
+            Array.Clear(buf, 0, buf.Length);
+            bufOff = 0;
+
+            /*
+            * Reset the underlying cipher.
+            */
+            cipher.Reset();
+        }
+    }
 }
diff --git a/crypto/test/src/crypto/test/CMacTest.cs b/crypto/test/src/crypto/test/CMacTest.cs
index 35f5735b9..d71b69f98 100644
--- a/crypto/test/src/crypto/test/CMacTest.cs
+++ b/crypto/test/src/crypto/test/CMacTest.cs
@@ -10,277 +10,293 @@ using Org.BouncyCastle.Utilities.Test;
 
 namespace Org.BouncyCastle.Crypto.Tests
 {
-	/**
-	 * CMAC tester - <a href="http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/tv/omac1-tv.txt">Official Test Vectors</a>.
-	 */
-	[TestFixture]
-	public class CMacTest
-		: SimpleTest
-	{
-		private static readonly byte[] keyBytes128 = Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c");
-		private static readonly byte[] keyBytes192 = Hex.Decode(
-			"8e73b0f7da0e6452c810f32b809079e5"
-			+ "62f8ead2522c6b7b");
-		private static readonly byte[] keyBytes256 = Hex.Decode(
-			"603deb1015ca71be2b73aef0857d7781"
-			+ "1f352c073b6108d72d9810a30914dff4");
+    /**
+     * CMAC tester - <a href="http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/tv/omac1-tv.txt">Official Test Vectors</a>.
+     */
+    [TestFixture]
+    public class CMacTest
+        : SimpleTest
+    {
+        private static readonly byte[] keyBytes128 = Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c");
+        private static readonly byte[] keyBytes192 = Hex.Decode(
+            "8e73b0f7da0e6452c810f32b809079e5"
+            + "62f8ead2522c6b7b");
+        private static readonly byte[] keyBytes256 = Hex.Decode(
+            "603deb1015ca71be2b73aef0857d7781"
+            + "1f352c073b6108d72d9810a30914dff4");
 
-		private static readonly byte[] input0 = Hex.Decode("");
-		private static readonly byte[] input16 = Hex.Decode("6bc1bee22e409f96e93d7e117393172a");
-		private static readonly byte[] input40 = Hex.Decode(
-			"6bc1bee22e409f96e93d7e117393172a"
-			+ "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411");
-		private static readonly byte[] input64 = Hex.Decode(
-			"6bc1bee22e409f96e93d7e117393172a"
-			+ "ae2d8a571e03ac9c9eb76fac45af8e51"
-			+ "30c81c46a35ce411e5fbc1191a0a52ef"
-			+ "f69f2445df4f9b17ad2b417be66c3710");
+        private static readonly byte[] input0 = Hex.Decode("");
+        private static readonly byte[] input16 = Hex.Decode("6bc1bee22e409f96e93d7e117393172a");
+        private static readonly byte[] input40 = Hex.Decode(
+            "6bc1bee22e409f96e93d7e117393172a"
+            + "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411");
+        private static readonly byte[] input64 = Hex.Decode(
+            "6bc1bee22e409f96e93d7e117393172a"
+            + "ae2d8a571e03ac9c9eb76fac45af8e51"
+            + "30c81c46a35ce411e5fbc1191a0a52ef"
+            + "f69f2445df4f9b17ad2b417be66c3710");
 
-		private static readonly byte[] output_k128_m0 = Hex.Decode("bb1d6929e95937287fa37d129b756746");
-		private static readonly byte[] output_k128_m16 = Hex.Decode("070a16b46b4d4144f79bdd9dd04a287c");
-		private static readonly byte[] output_k128_m40 = Hex.Decode("dfa66747de9ae63030ca32611497c827");
-		private static readonly byte[] output_k128_m64 = Hex.Decode("51f0bebf7e3b9d92fc49741779363cfe");
+        private static readonly byte[] output_k128_m0 = Hex.Decode("bb1d6929e95937287fa37d129b756746");
+        private static readonly byte[] output_k128_m16 = Hex.Decode("070a16b46b4d4144f79bdd9dd04a287c");
+        private static readonly byte[] output_k128_m40 = Hex.Decode("dfa66747de9ae63030ca32611497c827");
+        private static readonly byte[] output_k128_m64 = Hex.Decode("51f0bebf7e3b9d92fc49741779363cfe");
 
-		private static readonly byte[] output_k192_m0 = Hex.Decode("d17ddf46adaacde531cac483de7a9367");
-		private static readonly byte[] output_k192_m16 = Hex.Decode("9e99a7bf31e710900662f65e617c5184");
-		private static readonly byte[] output_k192_m40 = Hex.Decode("8a1de5be2eb31aad089a82e6ee908b0e");
-		private static readonly byte[] output_k192_m64 = Hex.Decode("a1d5df0eed790f794d77589659f39a11");
+        private static readonly byte[] output_k192_m0 = Hex.Decode("d17ddf46adaacde531cac483de7a9367");
+        private static readonly byte[] output_k192_m16 = Hex.Decode("9e99a7bf31e710900662f65e617c5184");
+        private static readonly byte[] output_k192_m40 = Hex.Decode("8a1de5be2eb31aad089a82e6ee908b0e");
+        private static readonly byte[] output_k192_m64 = Hex.Decode("a1d5df0eed790f794d77589659f39a11");
 
-		private static readonly byte[] output_k256_m0 = Hex.Decode("028962f61b7bf89efc6b551f4667d983");
-		private static readonly byte[] output_k256_m16 = Hex.Decode("28a7023f452e8f82bd4bf28d8c37c35c");
-		private static readonly byte[] output_k256_m40 = Hex.Decode("aaf3d8f1de5640c232f5b169b9c911e6");
-		private static readonly byte[] output_k256_m64 = Hex.Decode("e1992190549f6ed5696a2c056c315410");
+        private static readonly byte[] output_k256_m0 = Hex.Decode("028962f61b7bf89efc6b551f4667d983");
+        private static readonly byte[] output_k256_m16 = Hex.Decode("28a7023f452e8f82bd4bf28d8c37c35c");
+        private static readonly byte[] output_k256_m40 = Hex.Decode("aaf3d8f1de5640c232f5b169b9c911e6");
+        private static readonly byte[] output_k256_m64 = Hex.Decode("e1992190549f6ed5696a2c056c315410");
 
-		public CMacTest()
-		{
-		}
+        public CMacTest()
+        {
+        }
 
-		public override void PerformTest()
-		{
-			IBlockCipher cipher = new AesFastEngine();
-			IMac mac = new CMac(cipher, 128);
+        public override void PerformTest()
+        {
+            IBlockCipher cipher = new AesFastEngine();
+            IMac mac = new CMac(cipher, 128);
 
-			//128 bytes key
+            //128 bytes key
 
-			KeyParameter key = new KeyParameter(keyBytes128);
+            KeyParameter key = new KeyParameter(keyBytes128);
 
-			// 0 bytes message - 128 bytes key
-			mac.Init(key);
+            // 0 bytes message - 128 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input0, 0, input0.Length);
+            mac.BlockUpdate(input0, 0, input0.Length);
 
-			byte[] outBytes = new byte[16];
+            byte[] outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k128_m0))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k128_m0) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k128_m0))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m0) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 16 bytes message - 128 bytes key
-			mac.Init(key);
+            // 16 bytes message - 128 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input16, 0, input16.Length);
+            mac.BlockUpdate(input16, 0, input16.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k128_m16))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k128_m16) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k128_m16))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m16) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 40 bytes message - 128 bytes key
-			mac.Init(key);
+            // 40 bytes message - 128 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input40, 0, input40.Length);
+            mac.BlockUpdate(input40, 0, input40.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k128_m40))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k128_m40) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k128_m40))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m40) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 64 bytes message - 128 bytes key
-			mac.Init(key);
+            // 64 bytes message - 128 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input64, 0, input64.Length);
+            mac.BlockUpdate(input64, 0, input64.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k128_m64))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k128_m64) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k128_m64))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m64) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			//192 bytes key
-			key = new KeyParameter(keyBytes192);
+            //192 bytes key
+            key = new KeyParameter(keyBytes192);
 
-			// 0 bytes message - 192 bytes key
-			mac.Init(key);
+            // 0 bytes message - 192 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input0, 0, input0.Length);
+            mac.BlockUpdate(input0, 0, input0.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k192_m0))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k192_m0) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k192_m0))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m0) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 16 bytes message - 192 bytes key
-			mac.Init(key);
+            // 16 bytes message - 192 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input16, 0, input16.Length);
+            mac.BlockUpdate(input16, 0, input16.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k192_m16))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k192_m16) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k192_m16))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m16) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 40 bytes message - 192 bytes key
-			mac.Init(key);
+            // 40 bytes message - 192 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input40, 0, input40.Length);
+            mac.BlockUpdate(input40, 0, input40.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k192_m40))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k192_m40) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k192_m40))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m40) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 64 bytes message - 192 bytes key
-			mac.Init(key);
+            // 64 bytes message - 192 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input64, 0, input64.Length);
+            mac.BlockUpdate(input64, 0, input64.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k192_m64))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k192_m64) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k192_m64))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m64) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			//256 bytes key
+            //256 bytes key
 
-			key = new KeyParameter(keyBytes256);
+            key = new KeyParameter(keyBytes256);
 
-			// 0 bytes message - 256 bytes key
-			mac.Init(key);
+            // 0 bytes message - 256 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input0, 0, input0.Length);
+            mac.BlockUpdate(input0, 0, input0.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k256_m0))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k256_m0) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k256_m0))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m0) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 16 bytes message - 256 bytes key
-			mac.Init(key);
+            // 16 bytes message - 256 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input16, 0, input16.Length);
+            mac.BlockUpdate(input16, 0, input16.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k256_m16))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k256_m16) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k256_m16))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m16) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 40 bytes message - 256 bytes key
-			mac.Init(key);
+            // 40 bytes message - 256 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input40, 0, input40.Length);
+            mac.BlockUpdate(input40, 0, input40.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k256_m40))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k256_m40) + " got "
-					+ Hex.ToHexString(outBytes));
-			}
+            if (!AreEqual(outBytes, output_k256_m40))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m40) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-			// 64 bytes message - 256 bytes key
-			mac.Init(key);
+            // 64 bytes message - 256 bytes key
+            mac.Init(key);
 
-			mac.BlockUpdate(input64, 0, input64.Length);
+            mac.BlockUpdate(input64, 0, input64.Length);
 
-			outBytes = new byte[16];
+            outBytes = new byte[16];
 
-			mac.DoFinal(outBytes, 0);
+            mac.DoFinal(outBytes, 0);
 
-			if (!AreEqual(outBytes, output_k256_m64))
-			{
-				Fail("Failed - expected "
-					+ Hex.ToHexString(output_k256_m64) + " got "
-					+ Hex.ToHexString(outBytes));
-				}
-		}
+            if (!AreEqual(outBytes, output_k256_m64))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m64) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
 
-		public override string Name
-		{
-			get { return "CMac"; }
-		}
+            TestExceptions();
+        }
 
-		public static void Main(
-			string[] args)
-		{
-			RunTest(new CMacTest());
-		}
+        private void TestExceptions()
+        {
+            try 
+            {
+                CMac mac = new CMac(new AesEngine());
+                mac.Init(new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+                Fail("CMac does not accept IV");
+            }
+            catch(ArgumentException)
+            {
+                // Expected
+            }
+        }
 
-		[Test]
-		public void TestFunction()
-		{
-			string resultText = Perform().ToString();
+        public override string Name
+        {
+            get { return "CMac"; }
+        }
 
-			Assert.AreEqual(Name + ": Okay", resultText);
-		}
-	}
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new CMacTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
 }