private void gHASHBlock(byte[] Y, byte[] b, int off) { GcmUtilities.Xor(Y, b, off); multiplier.MultiplyH(Y); }
private void gHASHPartial(byte[] Y, byte[] b, int off, int len) { GcmUtilities.Xor(Y, b, off, len); multiplier.MultiplyH(Y); }
public int DoFinal(byte[] output, int outOff) { CheckStatus(); if (totalLength == 0) { InitCipher(); } int extra = bufOff; if (forEncryption) { Check.OutputLength(output, outOff, extra + macSize, "Output buffer too short"); } else { if (extra < macSize) { throw new InvalidCipherTextException("data too short"); } extra -= macSize; Check.OutputLength(output, outOff, extra, "Output buffer too short"); } if (extra > 0) { ProcessPartial(bufBlock, 0, extra, output, outOff); } atLength += (uint)atBlockPos; if (atLength > atLengthPre) { /* * Some AAD was sent after the cipher started. We determine the difference b/w the hash value * we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at). * Then we carry this difference forward by multiplying by H^c, where c is the number of (full or * partial) cipher-text blocks produced, and adjust the current hash. */ // Finish hash for partial AAD block if (atBlockPos > 0) { gHASHPartial(S_at, atBlock, 0, atBlockPos); } // Find the difference between the AAD hashes if (atLengthPre > 0) { GcmUtilities.Xor(S_at, S_atPre); } // Number of cipher-text blocks produced long c = (long)(((totalLength * 8) + 127) >> 7); // Calculate the adjustment factor byte[] H_c = new byte[16]; if (exp == null) { exp = new BasicGcmExponentiator(); exp.Init(H); } exp.ExponentiateX(c, H_c); // Carry the difference forward GcmUtilities.Multiply(S_at, H_c); // Adjust the current hash GcmUtilities.Xor(S, S_at); } // Final gHASH byte[] X = new byte[BlockSize]; Pack.UInt64_To_BE(atLength * 8UL, X, 0); Pack.UInt64_To_BE(totalLength * 8UL, X, 8); gHASHBlock(S, X); // T = MSBt(GCTRk(J0,S)) byte[] tag = new byte[BlockSize]; cipher.ProcessBlock(J0, 0, tag, 0); GcmUtilities.Xor(tag, S); int resultLen = extra; // We place into macBlock our calculated value for T this.macBlock = new byte[macSize]; Array.Copy(tag, 0, macBlock, 0, macSize); if (forEncryption) { // Append T to the message Array.Copy(macBlock, 0, output, outOff + bufOff, macSize); resultLen += macSize; } else { // Retrieve the T value from the message and compare to calculated one byte[] msgMac = new byte[macSize]; Array.Copy(bufBlock, extra, msgMac, 0, macSize); if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac)) { throw new InvalidCipherTextException("mac check in GCM failed"); } } Reset(false); return(resultLen); }