byte[] tag = null;
if (!forEncryption)
{
if (mainBlockPos < macSize)
{
throw new InvalidCipherTextException("data too short");
}
mainBlockPos -= macSize;
tag = new byte[macSize];
System.arraycopy(mainBlock, mainBlockPos, tag, 0, macSize);
}
/*
* HASH: Process any final partial block; compute final hash value
*/
if (hashBlockPos > 0)
{
OCB_extend(hashBlock, hashBlockPos);
updateHASH(L_Asterisk);
}
/*
* OCB-ENCRYPT/OCB-DECRYPT: Process any final partial block
*/
if (mainBlockPos > 0)
{
if (forEncryption)
{
OCB_extend(mainBlock, mainBlockPos);
xor(Checksum, mainBlock);
}
xor(OffsetMAIN, L_Asterisk);
byte[] Pad = new byte[16];
hashCipher.processBlock(OffsetMAIN, 0, Pad, 0);
xor(mainBlock, Pad);
System.arraycopy(mainBlock, 0, output, outOff, mainBlockPos);
if (!forEncryption)
{
OCB_extend(mainBlock, mainBlockPos);
xor(Checksum, mainBlock);
}
}
/*
* OCB-ENCRYPT/OCB-DECRYPT: Compute raw tag
*/
xor(Checksum, OffsetMAIN);
xor(Checksum, L_Dollar);
hashCipher.processBlock(Checksum, 0, Checksum, 0);
xor(Checksum, Sum);
this.macBlock = new byte[macSize];
System.arraycopy(Checksum, 0, macBlock, 0, macSize);
/*
* Validate or append tag and reset this cipher for the next run
*/
int resultLen = mainBlockPos;
if (forEncryption)
{
// Append tag to the message
System.arraycopy(macBlock, 0, output, outOff + resultLen, macSize);
resultLen += macSize;
}
else
{
// Compare the tag from the message with the calculated one
if (!Arrays.constantTimeAreEqual(macBlock, tag))
{
throw new InvalidCipherTextException("mac check in OCB failed");
}
}
reset(false);