private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
{
IMac cMac = new CbcBlockCipherMac(cipher, parameters.MacSize);
byte[] nonce = parameters.GetNonce();
byte[] associatedText = parameters.GetAssociatedText();
cMac.Init(parameters.Key);
//
// build b0
//
byte[] b0 = new byte[16];
if (associatedText != null && associatedText.Length != 0)
{
b0[0] |= 0x40;
}
b0[0] |= (byte)((((cMac.GetMacSize() - 2) / 2) & 0x7) << 3);
b0[0] |= (byte)(((15 - nonce.Length) - 1) & 0x7);
Array.Copy(nonce, 0, b0, 1, nonce.Length);
int q = dataLen;
int count = 1;
while (q > 0)
{
b0[b0.Length - count] = (byte)(q & 0xff);
q >>= 8;
count++;
}
cMac.BlockUpdate(b0, 0, b0.Length);
//
// process associated text
//
if (associatedText != null)
{
int extra;
if (associatedText.Length < ((1 << 16) - (1 << 8)))
{
cMac.Update((byte)(associatedText.Length >> 8));
cMac.Update((byte)associatedText.Length);
extra = 2;
}
else // can't go any higher than 2^32
{
cMac.Update((byte)0xff);
cMac.Update((byte)0xfe);
cMac.Update((byte)(associatedText.Length >> 24));
cMac.Update((byte)(associatedText.Length >> 16));
cMac.Update((byte)(associatedText.Length >> 8));
cMac.Update((byte)associatedText.Length);
extra = 6;
}
cMac.BlockUpdate(associatedText, 0, associatedText.Length);
extra = (extra + associatedText.Length) % 16;
if (extra != 0)
{
for (int i = 0; i != 16 - extra; i++)
{
cMac.Update((byte)0x00);
}
}
}
//
// add the text
//
cMac.BlockUpdate(data, dataOff, dataLen);
return cMac.DoFinal(macBlock, 0);
}