public override void Write(RecordType type, TlsVersion version, byte[] data) { var cipher = GetCipher().Cipher; // TODO parametrised from CipherSpec var explicitNonceLength = 8; var nonce = RandomGenerator.RandomBytes(explicitNonceLength); var aad = new byte[13]; Array.Copy(EndianBitConverter.Big.GetBytes(State.WriteSeqNum++), 0, aad, 0, 8); Array.Copy(new[] { (byte)type, version.Major, version.Major }, 0, aad, 8, 3); Array.Copy(EndianBitConverter.Big.GetBytes((ushort)data.Length), 0, aad, 11, 2); var payload = new byte[explicitNonceLength + data.Length + cipher.TagLength]; Array.Copy(nonce, payload, explicitNonceLength); cipher.Init(State.GetAEADParameters(false, aad, nonce)); var payloadLength = explicitNonceLength; payloadLength += cipher.Encrypt(data, 0, payload, payloadLength, data.Length); payloadLength += cipher.EncryptFinal(payload, payloadLength); Writer.Write(type); Writer.Write(version); Writer.Write((ushort)payloadLength); Writer.Write(payload, 0, payloadLength); }
public override Record Read(RecordType type, TlsVersion version, ushort length) { var cipher = GetCipher().Cipher; // TODO parametrised from CipherSpec var explicitNonceLength = 8; var nonce = Reader.ReadBytes(explicitNonceLength); var payload = Reader.ReadBytes(length - explicitNonceLength); var aad = new byte[13]; Array.Copy(EndianBitConverter.Big.GetBytes(State.ReadSeqNum++), 0, aad, 0, 8); Array.Copy(new[] { (byte)type, version.Major, version.Major }, 0, aad, 8, 3); Array.Copy(EndianBitConverter.Big.GetBytes((ushort)(length - explicitNonceLength - cipher.TagLength)), 0, aad, 11, 2); cipher.Init(State.GetAEADParameters(true, aad, nonce)); var plaintext = new byte[payload.Length - cipher.TagLength]; var plaintextLength = cipher.Decrypt(payload, 0, plaintext, 0, payload.Length - cipher.TagLength); plaintextLength += cipher.DecryptFinal(payload, plaintextLength, plaintext, plaintextLength); Array.Resize(ref plaintext, plaintextLength); return new Record(type, version, plaintext); }
public override void Write(RecordType type, TlsVersion version, byte[] data) { Writer.Write(type); Writer.Write(version); Writer.Write((ushort)data.Length); Writer.Write(data, 0, data.Length); }
public override Record Read(RecordType type, TlsVersion version, ushort length) { SecurityAssert.SAssert(length <= 0x4000); var data = Reader.ReadBytes(length); return new Record(type, version, data); }
public Record(RecordType type, TlsVersion version, byte[] data) { Type = type; Version = version; SecurityAssert.NotNull(data); Data = data; }
public override void Write(RecordType type, TlsVersion version, byte[] data) { var cipher = GetCipher(); var macAlgo = State.GetMAC(false); var mac = ComputeMAC(macAlgo, State.WriteSeqNum++, type, version, data); var iv = RandomGenerator.RandomBytes(cipher.BlockLength); var payloadLength = data.Length + macAlgo.HashSize / 8; var padding = (byte)(cipher.BlockLength - 1 - payloadLength % cipher.BlockLength); // TODO padding can be upto 255, so possible add more than the minimum payloadLength += padding + 1; var plaintext = new byte[payloadLength]; var payload = new byte[payloadLength]; var offset = 0; Array.Copy(data, 0, plaintext, offset, data.Length); offset += data.Length; Array.Copy(mac, 0, plaintext, offset, mac.Length); offset += mac.Length; for (; offset < payloadLength; offset++) { plaintext[offset] = padding; } cipher.Init(new IVParameter(State.GetBlockCipherParameters(false), iv)); cipher.Encrypt(plaintext, 0, payload, 0, plaintext.Length); Writer.Write(type); Writer.Write(version); Writer.Write((ushort)(iv.Length + payloadLength)); Writer.Write(iv); Writer.Write(payload); }
public override Record Read(RecordType type, TlsVersion version, ushort length) { var cipher = GetCipher(); var blockLength = cipher.BlockLength; var iv = Reader.ReadBytes(blockLength); cipher.Init(new IVParameter(State.GetBlockCipherParameters(true), iv)); var payload = Reader.ReadBytes(length - blockLength); var plaintext = new byte[payload.Length]; cipher.Decrypt(payload, 0, plaintext, 0, payload.Length); var macAlgo = State.GetMAC(true); var macLength = macAlgo.HashSize / 8; var paddingLength = plaintext[plaintext.Length - 1]; var contentLength = plaintext.Length - paddingLength - macLength - 1; SecurityAssert.SAssert(contentLength >= 0); //TODO constant time for (var i = plaintext.Length - 1; i > plaintext.Length - paddingLength; i--) { SecurityAssert.SAssert(plaintext[i] == paddingLength); } var mac = new byte[macLength]; Array.Copy(plaintext, contentLength, mac, 0, macLength); var content = new byte[contentLength]; Array.Copy(plaintext, 0, content, 0, content.Length); var computedMac = ComputeMAC(macAlgo, State.ReadSeqNum++, type, version, content); SecurityAssert.HashAssert(mac, computedMac); return new Record(type, version, content); }
private byte[] ComputeMAC(IDigest macAlgo, long seqNum, RecordType type, TlsVersion version, byte[] content) { macAlgo.Update(EndianBitConverter.Big.GetBytes(seqNum), 0, sizeof(long)); macAlgo.Update(new[] { (byte)type, version.Major, version.Major }, 0, 3); macAlgo.Update(EndianBitConverter.Big.GetBytes((ushort)content.Length), 0, sizeof(ushort)); macAlgo.Update(content, 0, content.Length); return macAlgo.Digest(); }
public TlsVersion DecideVersion(TlsVersion clientVersion) { return TlsVersion.TLS1_2; }
public static void Write(this EndianBinaryWriter writer, TlsVersion version) { writer.Write(version.Major); writer.Write(version.Minor); }
public abstract void Write(RecordType type, TlsVersion version, byte[] data);
public abstract Record Read(RecordType type, TlsVersion version, ushort length);