#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
#pragma warning disable
using System;
using System.Collections;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Modes;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
namespace BestHTTP.SecureProtocol.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, 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;
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();
}
}
}
#pragma warning restore
#endif