From fc763ffe88a7f22f51a314e8ebec2af5b901658c Mon Sep 17 00:00:00 2001 From: Tim Whittington Date: Wed, 16 Oct 2013 21:22:08 +1300 Subject: Port GMac implementation and tests from bc-java. --- crypto/src/crypto/macs/GMac.cs | 111 ++++++++++++++++++++++++++++ crypto/src/crypto/modes/EAXBlockCipher.cs | 5 ++ crypto/src/crypto/modes/GCMBlockCipher.cs | 5 ++ crypto/src/crypto/modes/IAeadBlockCipher.cs | 3 + 4 files changed, 124 insertions(+) create mode 100644 crypto/src/crypto/macs/GMac.cs (limited to 'crypto/src') 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 +{ + /// + /// The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication + /// 800-38D. + /// + /// + /// 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). + /// + public class GMac + : IMac + { + private readonly GcmBlockCipher cipher; + private readonly int macSizeBits; + + /// + /// Creates a GMAC based on the operation of a block cipher in GCM mode. + /// + /// + /// This will produce an authentication code the length of the block size of the cipher. + /// + /// the cipher to be used in GCM mode to generate the MAC. + public GMac(GcmBlockCipher cipher) + : this(cipher, 128) + { + } + + /// + /// Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode. + /// + /// + /// This will produce an authentication code the length of the block size of the cipher. + /// + /// the cipher to be used in GCM mode to generate the MAC. + /// the mac size to generate, in bits. Must be a multiple of 8 and >= 96 and <= 128. + public GMac(GcmBlockCipher cipher, int macSizeBits) + { + this.cipher = cipher; + this.macSizeBits = macSizeBits; + } + + /// + /// Initialises the GMAC - requires a + /// providing a and a nonce. + /// + 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 /// The name of the algorithm this cipher implements. string AlgorithmName { get; } + /// The block cipher underlying this algorithm. + IBlockCipher GetUnderlyingCipher(); + /// Initialise the cipher. /// Parameter can either be an AeadParameters or a ParametersWithIV object. /// Initialise for encryption if true, for decryption if false. -- cgit 1.5.1