From b999a754ac553719d4953eb866c0d8e9b2633c33 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Mon, 21 Jul 2014 13:07:18 +0700 Subject: Port a few more GCM/GMac updates --- crypto/src/crypto/macs/GMac.cs | 179 +++++++++++++++--------------- crypto/src/crypto/modes/GCMBlockCipher.cs | 15 ++- 2 files changed, 100 insertions(+), 94 deletions(-) (limited to 'crypto/src') 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 { - /// - /// 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; + /// + /// 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 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, between 96 and 128 (inclusive). - public GMac(GcmBlockCipher cipher, int macSizeBits) - { - this.cipher = cipher; - this.macSizeBits = macSizeBits; - } + /// + /// 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, between 32 and 128 (inclusive). + /// Sizes less than 96 are not recommended, but are supported for specialized applications. + 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; + /// + /// 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; + 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; } + /// + /// 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. + /// 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); -- cgit 1.5.1