diff options
author | Tim Whittington <bc@whittington.net.nz> | 2013-10-16 21:22:08 +1300 |
---|---|---|
committer | Tim Whittington <bc@whittington.net.nz> | 2013-10-20 20:51:28 +1300 |
commit | fc763ffe88a7f22f51a314e8ebec2af5b901658c (patch) | |
tree | 1e652a3ba1f12d4af2237dfc21068d3570fdd60d /crypto/src | |
parent | fixed line endings (diff) | |
download | BouncyCastle.NET-ed25519-fc763ffe88a7f22f51a314e8ebec2af5b901658c.tar.xz |
Port GMac implementation and tests from bc-java.
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/crypto/macs/GMac.cs | 111 | ||||
-rw-r--r-- | crypto/src/crypto/modes/EAXBlockCipher.cs | 5 | ||||
-rw-r--r-- | crypto/src/crypto/modes/GCMBlockCipher.cs | 5 | ||||
-rw-r--r-- | crypto/src/crypto/modes/IAeadBlockCipher.cs | 3 |
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> |