static void CalcHash(ICryptoTransform key, byte[] iv, byte[] data, int offset, int len, ulong seqNum, ulong header, ulong[] h, byte[] temp512) { ulong s1 = 0, s2 = 0; MulWithTable(h, s1, s2, seqNum, header, ref s1, ref s2); var end = offset + len / 16 * 16; for (var pos = offset; pos < end;) { MulWithTable2(h, s1, s2, data, pos, ref s1, ref s2); pos += 16; } if (end != offset + len) { ulong x1 = 0; ulong x2 = 0; for (int pos = end, b = 15; pos < offset + len; pos++, b--) { if (b >= 8) { x1 |= (ulong)data[pos] << (b - 8) * 8; } else { x2 |= (ulong)data[pos] << b * 8; } } MulWithTable(h, s1, s2, x1, x2, ref s1, ref s2); } MulWithTable(h, s1, s2, 13 * 8, (ulong)(len * 8), ref s1, ref s2); Utils.WriteUInt64(data, offset + len, s1); Utils.WriteUInt64(data, offset + len + 8, s2); Encrypt(data, offset + len, 16, key, iv, 1, temp512); }
static void CalcHash(ICryptoTransform key, byte[] iv, byte[] data, int offset, int len, ulong seqNum, ulong header, ulong[] h, byte[] temp512) { ulong s1 = 0, s2 = 0; // Additional data // Don't use table-based multiplication for the first block to avoid potential timing-attack vulnerabilities as described in // http://udspace.udel.edu/bitstream/handle/19716/9765/Bonan_Huang_thesis.pdf (Cache-collision timing attacks against AES-GCM) Mul(h[h.Length - 2], h[h.Length - 1], s1, s2, seqNum, header, ref s1, ref s2); // Ciphertext var end = offset + len / 16 * 16; for (var pos = offset; pos < end;) { MulWithTable2(h, s1, s2, data, pos, ref s1, ref s2); pos += 16; } if (end != offset + len) { ulong x1 = 0; ulong x2 = 0; for (int pos = end, b = 15; pos < offset + len; pos++, b--) { if (b >= 8) { x1 |= (ulong)data[pos] << (b - 8) * 8; } else { x2 |= (ulong)data[pos] << b * 8; } } MulWithTable(h, s1, s2, x1, x2, ref s1, ref s2); } // Length of additional data and ciphertext data MulWithTable(h, s1, s2, 13 * 8, (ulong)(len * 8), ref s1, ref s2); // Put the hash at the end of the data stream and encrypt it Utils.WriteUInt64(data, offset + len, s1); Utils.WriteUInt64(data, offset + len + 8, s2); Encrypt(data, offset + len, 16, key, iv, 1, temp512); }