예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);

        }
예제 #4
0
        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);
        }
예제 #5
0
        public Record(RecordType type, TlsVersion version, byte[] data)
        {
            Type = type;
            Version = version;

            SecurityAssert.NotNull(data);
            Data = data;
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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();
        }
예제 #9
0
 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);
 }
예제 #11
0
 public abstract void Write(RecordType type, TlsVersion version, byte[] data);
예제 #12
0
 public abstract Record Read(RecordType type, TlsVersion version, ushort length);