Пример #1
0
        public static ReadableBuffer SliceVector <[Primitive] T>(ref ReadableBuffer buffer) where T : struct
        {
            uint length = 0;

            if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
            {
                length = buffer.ReadBigEndian <byte>();
                buffer = buffer.Slice(sizeof(byte));
            }
            else if (typeof(T) == typeof(ushort) || typeof(T) == typeof(short))
            {
                length = buffer.ReadBigEndian <ushort>();
                buffer = buffer.Slice(sizeof(ushort));
            }
            else if (typeof(T) == typeof(uint) || typeof(T) == typeof(int))
            {
                length = buffer.ReadBigEndian <uint>();
                buffer = buffer.Slice(sizeof(uint));
            }
            else
            {
                Internal.ExceptionHelper.ThrowException(new InvalidCastException($"The type {typeof(T)} is not a primitave integer type"));
            }
            var returnBuffer = buffer.Slice(0, (int)length);

            buffer = buffer.Slice(returnBuffer.End);
            return(returnBuffer);
        }
Пример #2
0
        public override void HandleAlertMessage(ReadableBuffer messageBuffer)
        {
            var level = messageBuffer.ReadBigEndian <Alerts.AlertLevel>();

            messageBuffer = messageBuffer.Slice(sizeof(Alerts.AlertLevel));
            var description = messageBuffer.ReadBigEndian <Alerts.AlertDescription>();

            Alerts.AlertException.ThrowAlert(level, description, "Alert from the client");
        }
        public static bool HandleMessage(ref ReadableBuffer reader)
        {
            if (reader.Length < 4)
            {
                return(false);
            }

            var messageLength = reader.ReadBigEndian <ushort>();

            if (reader.Length < (messageLength + 4))
            {
                return(false);
            }
            messageLength = reader.ReadBigEndian <ushort>();
            reader        = reader.Slice(2);
            var messageType = (MessageTypes)reader.ReadBigEndian <ushort>();

            var messageBuff = reader.Slice(2, messageLength);

            switch (messageType)
            {
            case MessageTypes.LoginAck:
                try
                {
                    var md = new LoginResponse(ref messageBuff);
                    ///Fire off to low priority queue because it's not very important
                }
                catch (Exception ex)
                {
                    errorCount++;
                    Console.WriteLine("Number of errors" + errorCount);
                }
                break;

            case MessageTypes.SomeDataUpdate:
                try
                {
                    var md = new SomeDataUpdate(ref messageBuff);
                    ///Fire off to very important queue as its realtime
                }
                catch (Exception ex)
                {
                    errorCount++;
                    Console.WriteLine("Number of errors" + errorCount);
                }
                break;
            }


            return(true);
        }
Пример #4
0
 public static bool TryParse(ReadableBuffer payload, out WebSocketCloseResult result, out ushort?actualCloseCode)
 {
     if (payload.Length == 0)
     {
         // Empty payload is OK
         actualCloseCode = null;
         result          = new WebSocketCloseResult(WebSocketCloseStatus.Empty, string.Empty);
         return(true);
     }
     else if (payload.Length < 2)
     {
         actualCloseCode = null;
         result          = default(WebSocketCloseResult);
         return(false);
     }
     else
     {
         var status = payload.ReadBigEndian <ushort>();
         actualCloseCode = status;
         var description = string.Empty;
         payload = payload.Slice(2);
         if (payload.Length > 0)
         {
             description = payload.GetUtf8String();
         }
         result = new WebSocketCloseResult((WebSocketCloseStatus)status, description);
         return(true);
     }
 }
Пример #5
0
        public static RecordType ReadRecord(ref ReadableBuffer messageBuffer, State.IConnectionState state)
        {
            if (messageBuffer.Length < RecordHeaderLength)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, "The message buffer length is smaller than the record header length");
            }
            var recordType = messageBuffer.ReadBigEndian <RecordType>();
            var version    = messageBuffer.Slice(sizeof(RecordType)).ReadBigEndian <ushort>();
            var size       = messageBuffer.Slice(sizeof(RecordType) + sizeof(ushort)).ReadBigEndian <ushort>();

            if (state?.ReadKey == null)
            {
                messageBuffer = messageBuffer.Slice(RecordHeaderLength);
                return(recordType);
            }
            if ((TlsVersion)state.TlsRecordVersion == TlsVersion.Tls12)
            {
                state.ReadKey.DecryptWithAuthData(ref messageBuffer);
                return(recordType);
            }
            else
            {
                messageBuffer = messageBuffer.Slice(RecordHeaderLength);
                state.ReadKey.Decrypt(ref messageBuffer);
                RemovePadding(ref messageBuffer);
                recordType    = messageBuffer.Slice(messageBuffer.Length - sizeof(RecordType)).ReadBigEndian <RecordType>();
                messageBuffer = messageBuffer.Slice(0, messageBuffer.Length - sizeof(RecordType));
                return(recordType);
            }
        }
Пример #6
0
        public static int ReadBigEndian24bit(this ReadableBuffer buffer)
        {
            uint contentSize = buffer.ReadBigEndian <ushort>();

            contentSize = (contentSize << 8) + buffer.Slice(2).ReadBigEndian <byte>();
            return((int)contentSize);
        }
Пример #7
0
        public static bool TryGetFrame(ref ReadableBuffer buffer, out ReadableBuffer messageBuffer)
        {
            messageBuffer = default(ReadableBuffer);
            if (buffer.Length < 5)
            {
                return(false);
            }
            var frameType = buffer.ReadBigEndian <RecordType>();

            if (frameType != RecordType.Alert && frameType != RecordType.Application &&
                frameType != RecordType.Handshake)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"unknown frame type {frameType}");
            }
            var version = buffer.Slice(1).ReadBigEndian <ushort>();

            if (version < 0x0300 || version > 0x0400)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"The frame version was outside the range {version}");
            }
            var length = buffer.Slice(3).ReadBigEndian <ushort>();

            if (buffer.Length >= (length + RecordHeaderLength))
            {
                messageBuffer = buffer.Slice(0, length + RecordHeaderLength);
                buffer        = buffer.Slice(length + RecordHeaderLength);
                return(true);
            }
            return(false);
        }
Пример #8
0
        public unsafe IKeyshareInstance GetKeyshareFromNamedGroups(ReadableBuffer buffer)
        {
            if (buffer.Length % 2 != 0)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "The buffer for supported groups is not divisable by 2");
            }
            var numberOfGroups = buffer.Length / 2;
            var peerGroupList  = stackalloc NamedGroup[numberOfGroups];

            for (var i = 0; i < numberOfGroups; i++)
            {
                peerGroupList[i] = buffer.ReadBigEndian <NamedGroup>();
                buffer           = buffer.Slice(sizeof(NamedGroup));
            }

            for (var i = 0; i < _priorityOrderedKeyExchanges.Length; i++)
            {
                for (var x = 0; x < numberOfGroups; x++)
                {
                    if (peerGroupList[x] == _priorityOrderedKeyExchanges[i])
                    {
                        var ks = _keyShareProvider.GetKeyShareInstance(peerGroupList[x]);
                        if (ks != null)
                        {
                            return(ks);
                        }
                    }
                }
            }
            Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.insufficient_security, "Could not agree on a keyshare from named groups");
            return(null);
        }
Пример #9
0
        public unsafe CipherSuite GetCipherSuiteFromExtension(ReadableBuffer buffer, TlsVersion version)
        {
            var list = GetCipherSuites(version);

            if (buffer.Length % 2 != 0)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Cipher suite extension is not divisable by zero");
            }
            var numberOfCiphers = buffer.Length / 2;
            var peerCipherList  = stackalloc ushort[numberOfCiphers];

            for (var i = 0; i < numberOfCiphers; i++)
            {
                peerCipherList[i] = buffer.ReadBigEndian <ushort>();
                buffer            = buffer.Slice(sizeof(ushort));
            }

            for (var i = 0; i < list.Length; i++)
            {
                for (var x = 0; x < numberOfCiphers; x++)
                {
                    if (peerCipherList[x] == list[i].CipherCode)
                    {
                        return(list[i]);
                    }
                }
            }
            Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.insufficient_security, "Failed to get a bulk cipher from the cipher extensions");
            return(null);
        }
Пример #10
0
        public override void HandleAlertMessage(ReadableBuffer messageBuffer)
        {
            var level = messageBuffer.ReadBigEndian <Alerts.AlertLevel>();

            messageBuffer = messageBuffer.Slice(sizeof(Alerts.AlertLevel));
            var description = messageBuffer.ReadBigEndian <Alerts.AlertDescription>();

            if (level == Alerts.AlertLevel.Warning && description == Alerts.AlertDescription.end_of_early_data && State == StateType.WaitEarlyDataFinished)
            {
                //0RTT data finished so we switch the reader key to the handshake key and wait for
                //the client to send it's finish message
                _readKey?.Dispose();
                _readKey = KeySchedule.GenerateClientHandshakeKey();
                ChangeState(StateType.WaitClientFinished);
                return;
            }
            Alerts.AlertException.ThrowAlert(level, description, "Alert from the client");
        }
        internal static TlsFrameType CheckForFrameType(this ReadableBuffer buffer, out ReadCursor endOfMessage)
        {
            endOfMessage = buffer.Start;
            //Need at least 5 bytes to be useful
            if (buffer.Length < 5)
            {
                return(TlsFrameType.Incomplete);
            }

            var messageType = (TlsFrameType)buffer.ReadBigEndian <byte>();

            buffer = buffer.Slice(1);

            //Check it's a valid frametype for what we are expecting
            if (messageType != TlsFrameType.AppData && messageType != TlsFrameType.Alert && messageType != TlsFrameType.ChangeCipherSpec && messageType != TlsFrameType.Handshake)
            {
                return(TlsFrameType.Invalid);
            }

            //now we get the version

            var version = buffer.ReadBigEndian <ushort>();

            buffer = buffer.Slice(2);

            if (version < 0x300 || version >= 0x500)
            {
                return(TlsFrameType.Invalid);
            }

            var length = buffer.ReadBigEndian <ushort>();

            buffer = buffer.Slice(2);

            if (buffer.Length >= length)
            {
                endOfMessage = buffer.Slice(0, length).End;
                return(messageType);
            }

            return(TlsFrameType.Incomplete);
        }
Пример #12
0
        public static void ReadExtensionListTls(ref ReadableBuffer buffer, IConnectionState connectionState)
        {
            var            listLength          = buffer.ReadBigEndian <ushort>();
            ReadableBuffer signatureAlgoBuffer = default(ReadableBuffer);

            buffer = buffer.Slice(sizeof(ushort));
            if (buffer.Length < listLength)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, "The extension list is not as long as the header says");
            }
            var currentbuffer = buffer.Slice(0, listLength);

            buffer = buffer.Slice(currentbuffer.End);
            while (currentbuffer.Length > 3)
            {
                var extensionType   = currentbuffer.ReadBigEndian <ExtensionType>();
                var extensionLength = currentbuffer.Slice(sizeof(ExtensionType)).ReadBigEndian <ushort>();
                currentbuffer = currentbuffer.Slice(sizeof(ExtensionType) + sizeof(ushort));
                if (currentbuffer.Length < extensionLength)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"The extension of type {extensionType} is too long for the remaining buffer");
                }
                var extensionBuffer = currentbuffer.Slice(0, extensionLength);
                currentbuffer = currentbuffer.Slice(extensionLength);
                switch (extensionType)
                {
                case ExtensionType.server_name:
                    ReadServerName(extensionBuffer, connectionState);
                    break;

                //case ExtensionType.signature_algorithms:
                //    signatureAlgoBuffer = extensionBuffer;
                //    break;
                case ExtensionType.supported_groups:
                    if (connectionState.CipherSuite.ExchangeType == KeyExchange.KeyExchangeType.Ecdhe)
                    {
                        connectionState.CryptoProvider.GetKeyshareFromNamedGroups(extensionBuffer);
                    }
                    break;

                case ExtensionType.renegotiation_info:
                    ReadRenegotiationInfo(extensionBuffer, connectionState);
                    break;
                }
            }
            //Wait until the end to check the signature, here we select the
            //certificate and this could depend on the server name indication
            //as well as the trusted CA roots.
            if (signatureAlgoBuffer.Length != 0)
            {
                ReadSignatureScheme(signatureAlgoBuffer, connectionState);
            }
        }
Пример #13
0
 public void MatchServerName(ReadableBuffer buffer, IConnectionState state)
 {
     buffer = BufferExtensions.SliceVector <ushort>(ref buffer);
     while (buffer.Length > 0)
     {
         var nameType = buffer.ReadBigEndian <byte>();
         buffer = buffer.Slice(sizeof(byte));
         var nameBuffer = BufferExtensions.SliceVector <ushort>(ref buffer);
         if (nameType == 0)
         {
             state.ServerName = nameBuffer.GetUtf8String();
         }
     }
 }
Пример #14
0
        public static bool TryGetFrame(ref ReadableBuffer buffer, out ReadableBuffer messageBuffer, out HandshakeType messageType)
        {
            messageType   = HandshakeType.certificate;
            messageBuffer = default(ReadableBuffer);

            if (buffer.Length < 4)
            {
                return(false);
            }
            messageType = buffer.ReadBigEndian <HandshakeType>();
            var length = buffer.Slice(sizeof(HandshakeType)).ReadBigEndian24bit();

            if (buffer.Length < (length + 4))
            {
                return(false);
            }
            messageBuffer = buffer.Slice(0, HandshakeHeaderSize + length);
            buffer        = buffer.Slice(HandshakeHeaderSize + length);
            return(true);
        }
Пример #15
0
        public unsafe void GetCipherSuiteFromExtension(ReadableBuffer buffer, IConnectionState state)
        {
            var list = GetCipherSuites(state.Version);

            if (buffer.Length % 2 != 0)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Cipher suite extension is not divisable by zero");
            }
            var numberOfCiphers = buffer.Length / 2;
            var peerCipherList  = stackalloc ushort[numberOfCiphers];

            for (var i = 0; i < numberOfCiphers; i++)
            {
                peerCipherList[i] = buffer.ReadBigEndian <ushort>();
                buffer            = buffer.Slice(sizeof(ushort));
                if (peerCipherList[i] == 0x00FF)
                {
                    state.SecureRenegotiation = true;
                }
            }
            for (var i = 0; i < list.Length; i++)
            {
                for (var x = 0; x < numberOfCiphers; x++)
                {
                    var suite = list[i];

                    if (peerCipherList[x] == suite.CipherCode)
                    {
                        if (suite.RequiredCertificateType == CertificateType.anonymous || _certificateList.GetCertificate(null, (SignatureScheme)((ushort)suite.HashType << 8 | (ushort)suite.RequiredCertificateType)) != null)
                        {
                            state.CipherSuite = list[i];
                            return;
                        }
                    }
                }
            }
            Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.insufficient_security, "Failed to get a bulk cipher from the cipher extensions");
        }
Пример #16
0
 public static ReadableBuffer SliceBigEndian <[Primitive] T>(this ReadableBuffer buffer, out T value) where T : struct
 {
     value = buffer.ReadBigEndian <T>();
     return(buffer.Slice(Unsafe.SizeOf <T>()));
 }
Пример #17
0
        public static void ReadExtensionListTls13(ref ReadableBuffer buffer, IConnectionStateTls13 connectionState)
        {
            ReadableBuffer signatureAlgoBuffer = default(ReadableBuffer);
            ReadableBuffer pskBuffer           = default(ReadableBuffer);

            if (buffer.Length < sizeof(ushort))
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"Extension list is not at least the size of a ushort");
            }
            var listLength = buffer.ReadBigEndian <ushort>();

            buffer = buffer.Slice(sizeof(ushort));
            if (buffer.Length < listLength)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, "The extension list is not as long as the header says");
            }
            var currentbuffer = buffer.Slice(0, listLength);

            buffer = buffer.Slice(currentbuffer.End);
            while (currentbuffer.Length > 3)
            {
                var extensionType   = currentbuffer.ReadBigEndian <ExtensionType>();
                var extensionLength = currentbuffer.Slice(sizeof(ExtensionType)).ReadBigEndian <ushort>();
                currentbuffer = currentbuffer.Slice(sizeof(ExtensionType) + sizeof(ushort));
                if (currentbuffer.Length < extensionLength)
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, $"The extension of type {extensionType} is too long for the remaining buffer");
                }
                var extensionBuffer = currentbuffer.Slice(0, extensionLength);
                currentbuffer = currentbuffer.Slice(extensionLength);
                switch (extensionType)
                {
                case ExtensionType.server_name:
                    ReadServerName(extensionBuffer, connectionState);
                    break;

                case ExtensionType.key_share:
                    ReadKeyshare(extensionBuffer, connectionState);
                    break;

                case ExtensionType.supported_groups:
                    ReadSupportedGroups(extensionBuffer, connectionState);
                    break;

                case ExtensionType.signature_algorithms:
                    signatureAlgoBuffer = extensionBuffer;
                    break;

                case ExtensionType.application_layer_protocol_negotiation:
                    ReadApplicationProtocolExtension(extensionBuffer, connectionState);
                    break;

                case ExtensionType.pre_shared_key:
                    pskBuffer = extensionBuffer;
                    break;

                case ExtensionType.psk_key_exchange_modes:
                    ReadPskKeyExchangeMode(extensionBuffer, connectionState);
                    break;

                case ExtensionType.certificate_authorities:
                    break;

                case ExtensionType.early_data:
                    ReadEarlyData(extensionBuffer, connectionState);
                    break;
                }
            }
            //Wait until the end to check the signature, here we select the
            //certificate and this could depend on the server name indication
            //as well as the trusted CA roots.
            if (signatureAlgoBuffer.Length != 0)
            {
                ReadSignatureScheme(signatureAlgoBuffer, connectionState);
            }
            //We only check if we want to use a PSK at the end because we need the
            //entire state (ciphers okay, and all the other information is correct
            //before we bother
            if (pskBuffer.Length != 0)
            {
                ReadPskKey(pskBuffer, connectionState);
            }
            if (currentbuffer.Length != 0)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.decode_error, "there was data after the extension list which is invalid");
            }
        }
        public SomeDataUpdate(ref ReadableBuffer buffer)
        {
            Bid1   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Bid2   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Bid3   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Bid4   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Ask1   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Ask2   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Ask3   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Ask4   = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Size1  = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Size2  = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Size3  = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            Size4  = buffer.ReadBigEndian <int>();
            buffer = buffer.Slice(4);
            ReadableBuffer stringBuffer;
            ReadCursor     endCursor;

            buffer.TrySliceTo(0x00, out stringBuffer, out endCursor);

            SecurityCode = stringBuffer.GetAsciiString();
            buffer       = buffer.Slice(endCursor).Slice(1);
        }
Пример #19
0
 public LoginResponse(ref ReadableBuffer messageBuffer)
 {
     MessageId     = messageBuffer.ReadBigEndian <int>();
     messageBuffer = messageBuffer.Slice(4);
 }