summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2013-11-01 19:44:48 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2013-11-01 19:44:48 +0700
commit364610a7ff859c087719e3b3ce653864b7ee3ac3 (patch)
tree442dc99df030695850c8bf883260f0ace2aab9b6 /crypto/src
parentFix XML comment (diff)
parentPort GMac implementation and tests from bc-java. (diff)
downloadBouncyCastle.NET-ed25519-364610a7ff859c087719e3b3ce653864b7ee3ac3.tar.xz
Merge branch 'feature/gmac' of git://github.com/timw/bc-csharp
Conflicts:
	crypto/crypto.mdp
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/crypto/macs/GMac.cs111
-rw-r--r--crypto/src/crypto/modes/EAXBlockCipher.cs5
-rw-r--r--crypto/src/crypto/modes/GCMBlockCipher.cs5
-rw-r--r--crypto/src/crypto/modes/IAeadBlockCipher.cs3
4 files changed, 124 insertions, 0 deletions
diff --git a/crypto/src/crypto/macs/GMac.cs b/crypto/src/crypto/macs/GMac.cs
new file mode 100644
index 000000000..12ca68f90
--- /dev/null
+++ b/crypto/src/crypto/macs/GMac.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+	/// <summary>
+	/// The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication
+	/// 800-38D.
+	/// </summary>
+	/// <remarks>
+	/// GMac is an invocation of the GCM mode where no data is encrypted (i.e. all input data to the Mac
+	/// is processed as additional authenticated data with the underlying GCM block cipher).
+	/// </remarks>
+	public class GMac 
+		: IMac
+	{
+	    private readonly GcmBlockCipher cipher;
+		private readonly int macSizeBits;
+
+		/// <summary>
+		/// Creates a GMAC based on the operation of a block cipher in GCM mode.
+		/// </summary>
+		/// <remarks>
+		/// This will produce an authentication code the length of the block size of the cipher.
+		/// </remarks>
+		/// <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+		public GMac(GcmBlockCipher cipher)
+			: this(cipher, 128)
+	    {
+	    }
+
+		/// <summary>
+		/// Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
+		/// </summary>
+		/// <remarks>
+		/// This will produce an authentication code the length of the block size of the cipher.
+		/// </remarks>
+		/// <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+		/// <param name="macSizeBits">the mac size to generate, in bits. Must be a multiple of 8 and >= 96 and <= 128.</param>
+		public GMac(GcmBlockCipher cipher, int macSizeBits)
+	    {
+	        this.cipher = cipher;
+	        this.macSizeBits = macSizeBits;
+	    }
+
+		/// <summary>
+		/// Initialises the GMAC - requires a <see cref="Org.BouncyCastle.Crypto.Parameters.ParametersWithIV"/> 
+		/// providing a <see cref="Org.BouncyCastle.Crypto.Parameters.KeyParameter"/> and a nonce.
+		/// </summary>
+	    public void Init(ICipherParameters parameters)
+	    {
+			if (parameters is ParametersWithIV)
+	        {
+				ParametersWithIV param = (ParametersWithIV)parameters;
+
+	            byte[] iv = param.GetIV();
+	            KeyParameter keyParam = (KeyParameter)param.Parameters;
+
+	            // GCM is always operated in encrypt mode to calculate MAC
+	            cipher.Init(true, new AeadParameters(keyParam, macSizeBits, iv));
+	        }
+	        else
+	        {
+	            throw new ArgumentException("GMAC requires ParametersWithIV");
+	        }
+	    }
+
+	    public string AlgorithmName
+	    {
+			get { return cipher.GetUnderlyingCipher().AlgorithmName + "-GMAC"; }
+	    }
+
+		public int GetMacSize()
+	    {
+	        return macSizeBits / 8;
+	    }
+
+	    public void Update(byte input) 
+	    {
+			cipher.ProcessAadByte(input);
+	    }
+
+		public void BlockUpdate(byte[] input, int inOff, int len)
+	    {
+			cipher.ProcessAadBytes(input, inOff, len);
+	    }
+
+		public int DoFinal(byte[] output, int outOff)
+	    {
+	        try
+	        {
+	            return cipher.DoFinal(output, outOff);
+	        }
+			catch (InvalidCipherTextException e)
+	        {
+	            // Impossible in encrypt mode
+	            throw new InvalidOperationException(e.ToString());
+	        }
+	    }
+
+	    public void Reset()
+	    {
+	        cipher.Reset();
+	    }
+	}
+}
diff --git a/crypto/src/crypto/modes/EAXBlockCipher.cs b/crypto/src/crypto/modes/EAXBlockCipher.cs
index bb027b597..5ccc69b66 100644
--- a/crypto/src/crypto/modes/EAXBlockCipher.cs
+++ b/crypto/src/crypto/modes/EAXBlockCipher.cs
@@ -65,6 +65,11 @@ namespace Org.BouncyCastle.Crypto.Modes
 			get { return cipher.GetUnderlyingCipher().AlgorithmName + "/EAX"; }
 		}
 
+		public IBlockCipher GetUnderlyingCipher()
+		{
+			return cipher;
+		}
+
 		public virtual int GetBlockSize()
 		{
 			return cipher.GetBlockSize();
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index 95fe6f7ec..74b895e7b 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -69,6 +69,11 @@ namespace Org.BouncyCastle.Crypto.Modes
 			get { return cipher.AlgorithmName + "/GCM"; }
 		}
 
+		public IBlockCipher GetUnderlyingCipher()
+		{
+			return cipher;
+		}
+
 		public virtual int GetBlockSize()
 		{
 			return BlockSize;
diff --git a/crypto/src/crypto/modes/IAeadBlockCipher.cs b/crypto/src/crypto/modes/IAeadBlockCipher.cs
index 06bc50488..52c4ff428 100644
--- a/crypto/src/crypto/modes/IAeadBlockCipher.cs
+++ b/crypto/src/crypto/modes/IAeadBlockCipher.cs
@@ -11,6 +11,9 @@ namespace Org.BouncyCastle.Crypto.Modes
 		/// <summary>The name of the algorithm this cipher implements.</summary>
 		string AlgorithmName { get; }
 
+		/// <summary>The block cipher underlying this algorithm.</summary>
+		IBlockCipher GetUnderlyingCipher();
+
 		/// <summary>Initialise the cipher.</summary>
 		/// <remarks>Parameter can either be an AeadParameters or a ParametersWithIV object.</remarks>
 		/// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>