diff --git a/crypto/src/crypto/macs/GMac.cs b/crypto/src/crypto/macs/GMac.cs
index eb340ddbc..f2c3990c6 100644
--- a/crypto/src/crypto/macs/GMac.cs
+++ b/crypto/src/crypto/macs/GMac.cs
@@ -8,104 +8,105 @@ 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>
+ /// 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 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, between 96 and 128 (inclusive).</param>
- public GMac(GcmBlockCipher cipher, int macSizeBits)
- {
- this.cipher = cipher;
- this.macSizeBits = macSizeBits;
- }
+ /// <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, between 32 and 128 (inclusive).
+ /// Sizes less than 96 are not recommended, but are supported for specialized applications.</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;
+ /// <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;
+ 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");
- }
- }
+ // 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 string AlgorithmName
+ {
+ get { return cipher.GetUnderlyingCipher().AlgorithmName + "-GMAC"; }
+ }
- public int GetMacSize()
- {
- return macSizeBits / 8;
- }
+ public int GetMacSize()
+ {
+ return macSizeBits / 8;
+ }
- public void Update(byte input)
- {
- cipher.ProcessAadByte(input);
- }
+ public void Update(byte input)
+ {
+ cipher.ProcessAadByte(input);
+ }
- public void BlockUpdate(byte[] input, int inOff, int len)
- {
- cipher.ProcessAadBytes(input, inOff, len);
- }
+ 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 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();
- }
- }
+ public void Reset()
+ {
+ cipher.Reset();
+ }
+ }
}
diff --git a/crypto/src/crypto/modes/GCMBlockCipher.cs b/crypto/src/crypto/modes/GCMBlockCipher.cs
index 91858f6f5..2e2ac2eca 100644
--- a/crypto/src/crypto/modes/GCMBlockCipher.cs
+++ b/crypto/src/crypto/modes/GCMBlockCipher.cs
@@ -79,6 +79,10 @@ namespace Org.BouncyCastle.Crypto.Modes
return BlockSize;
}
+ /// <remarks>
+ /// MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
+ /// Sizes less than 96 are not recommended, but are supported for specialized applications.
+ /// </remarks>
public virtual void Init(
bool forEncryption,
ICipherParameters parameters)
@@ -96,7 +100,7 @@ namespace Org.BouncyCastle.Crypto.Modes
initialAssociatedText = param.GetAssociatedText();
int macSizeBits = param.MacSize;
- if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0)
+ if (macSizeBits < 32 || macSizeBits > 128 || macSizeBits % 8 != 0)
{
throw new ArgumentException("Invalid value for MAC size: " + macSizeBits);
}
@@ -126,9 +130,7 @@ namespace Org.BouncyCastle.Crypto.Modes
throw new ArgumentException("IV must be at least 1 byte");
}
- // TODO This should be configurable by Init parameters
- // (but must be 16 if nonce length not 12) (BlockSize?)
-// this.tagLength = 16;
+ // TODO Restrict macSize to 16 if nonce length not 12?
// Cipher always used in forward mode
// if keyParam is null we're reusing the last key.
@@ -143,6 +145,10 @@ namespace Org.BouncyCastle.Crypto.Modes
multiplier.Init(H);
exp = null;
}
+ else if (this.H == null)
+ {
+ throw new ArgumentException("Key must be specified in initial init");
+ }
this.J0 = new byte[BlockSize];
@@ -381,7 +387,6 @@ namespace Org.BouncyCastle.Crypto.Modes
gHASHBlock(S, X);
- // TODO Fix this if tagLength becomes configurable
// T = MSBt(GCTRk(J0,S))
byte[] tag = new byte[BlockSize];
cipher.ProcessBlock(J0, 0, tag, 0);
|