internal override bool Decrypt(int recordType, int version, byte[] data, ref int off, ref int len) { off += 8; len -= 24; IO.Enc64be(seq, tmp, 0); IO.WriteHeader(recordType, version, len, tmp, 8); IO.Enc64be(13 << 3, tmp, 13); IO.Enc64be((ulong)len << 3, tmp, 21); for (int i = 0; i < 16; i++) { tag[i] = 0; } GHASH.Run(tag, h, tmp, 0, 13); GHASH.Run(tag, h, data, off, len); GHASH.Run(tag, h, tmp, 13, 16); seq++; Array.Copy(data, off - 8, iv, 4, 8); bc.CTRRun(iv, 2, data, off, len); bc.CTRRun(iv, 1, data, off + len, 16); int z = 0; for (int i = 0; i < 16; i++) { z |= tag[i] ^ data[off + len + i]; } return(z == 0); }
internal override void Encrypt(int recordType, int version, byte[] data, ref int off, ref int len) { /* * Explicit nonce is the encoded sequence number. We * encrypt the data itself; the counter starts at 2 * (value 1 is for the authentication tag). */ IO.Enc64be(seq, data, off - 8); Array.Copy(data, off - 8, iv, 4, 8); bc.CTRRun(iv, 2, data, off, len); /* * For the authentication tag: * header = sequence + 5-byte "plain" header * footer = the two relevant lengths (in bits) */ IO.Enc64be(seq, tmp, 0); IO.WriteHeader(recordType, version, len, tmp, 8); IO.Enc64be(13 << 3, tmp, 13); IO.Enc64be((ulong)len << 3, tmp, 21); /* * Compute clear authentication tag. */ for (int i = 0; i < 16; i++) { tag[i] = 0; } GHASH.Run(tag, h, tmp, 0, 13); GHASH.Run(tag, h, data, off, len); GHASH.Run(tag, h, tmp, 13, 16); /* * Copy authentication tag and apply final encryption on it. */ Array.Copy(tag, 0, data, off + len, 16); bc.CTRRun(iv, 1, data, off + len, 16); /* * Each record uses one sequence number. */ seq++; /* * Write encrypted header and return adjusted offset/length. */ off -= 13; len += 24; IO.WriteHeader(recordType, version, len, data, off); len += 5; }