Example #1
0
        public void RegisterSessionTicket(ReadableBuffer buffer)
        {
            //slice off the head first
            buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize);
            uint ticketAge, ageRandom;

            buffer = buffer.SliceBigEndian(out ticketAge);
            buffer = buffer.SliceBigEndian(out ageRandom);
            var ticketData = BufferExtensions.SliceVector <ushort>(ref buffer);

            if (buffer.Length > 0)
            {
                //Extensions
                buffer = BufferExtensions.SliceVector <ushort>(ref buffer);
                if (buffer.Length > 0)
                {
                    //seems we can resume data
                    ExtensionType type;
                    buffer = buffer.SliceBigEndian(out type);
                    if (type != ExtensionType.ticket_early_data_info)
                    {
                        Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Early session ticket received had an invalid extension");
                    }
                }
            }
        }
Example #2
0
        public static void ReadServerHello(ReadableBuffer readable, IConnectionStateTls13 connectionState)
        {
            var    original = readable;
            ushort version, cipherCode;

            readable = readable.Slice(HandshakeProcessor.HandshakeHeaderSize);
            readable = readable.SliceBigEndian(out version);
            //skip random
            readable = readable.Slice(RandomLength);
            readable = readable.SliceBigEndian(out cipherCode);
            connectionState.CipherSuite = connectionState.CryptoProvider.GetCipherSuiteFromCode(cipherCode, connectionState.Version);
            if (connectionState.CipherSuite == null)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "Could not get a cipher suite during server hello");
            }
            connectionState.StartHandshakeHash(original);
            readable = BufferExtensions.SliceVector <ushort>(ref readable);
            ExtensionType ext;

            readable = readable.SliceBigEndian(out ext);
            if (ext != ExtensionType.key_share)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "There was no keyshare on the server hello");
            }
            readable = BufferExtensions.SliceVector <ushort>(ref readable);
            NamedGroup group;

            readable = readable.SliceBigEndian(out group);
            if (group != connectionState.KeyShare.NamedGroup)
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.illegal_parameter, "The named group didn't match the keyshare during server hello");
            }
            readable = BufferExtensions.SliceVector <ushort>(ref readable);
            connectionState.KeyShare.SetPeerKey(readable);
        }
Example #3
0
        public unsafe static WritableBuffer SendKeyExchange(WritableBuffer buffer, IConnectionStateTls12 connectionState)
        {
            var messageLength = 4 + connectionState.KeyShare.KeyExchangeSize;

            buffer.Ensure(messageLength);
            var bookMark = buffer.Memory;

            buffer.WriteBigEndian(ECCurveType.named_curve);
            buffer.WriteBigEndian(connectionState.KeyShare.NamedGroup);
            buffer.WriteBigEndian((byte)connectionState.KeyShare.KeyExchangeSize);
            connectionState.KeyShare.WritePublicKey(ref buffer);

            buffer.WriteBigEndian(connectionState.SignatureScheme);
            BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) =>
            {
                var tempBuffer = stackalloc byte[connectionState.ClientRandom.Length * 2 + messageLength];
                var tmpSpan    = new Span <byte>(tempBuffer, connectionState.ClientRandom.Length * 2 + messageLength);
                connectionState.ClientRandom.CopyTo(tmpSpan);
                tmpSpan = tmpSpan.Slice(connectionState.ClientRandom.Length);
                connectionState.ServerRandom.CopyTo(tmpSpan);
                tmpSpan = tmpSpan.Slice(connectionState.ServerRandom.Length);
                bookMark.Span.Slice(0, messageLength).CopyTo(tmpSpan);
                connectionState.Certificate.SignHash(connectionState.CryptoProvider.HashProvider,
                                                     connectionState.SignatureScheme, ref writer, tempBuffer, connectionState.ClientRandom.Length * 2 + messageLength);
                return(writer);
            }, connectionState);

            return(buffer);
        }
Example #4
0
        public static void ReadApplicationProtocolExtension(ReadableBuffer buffer, IConnectionState connectionState)
        {
            buffer = BufferExtensions.SliceVector <ushort>(ref buffer);

            //if(connectionState.Listener.ServerNameProvider.MatchServerName(buffer))
            //buffer.Equals()
        }
Example #5
0
        public static WritableBuffer CreateNewSessionKey(WritableBuffer buffer, IConnectionStateTls13 state)
        {
            var lifetime = TicketLifeTimeInHours * 60 * 60;

            buffer.WriteBigEndian((uint)lifetime);
            buffer.Ensure(4);
            state.CryptoProvider.FillWithRandom(buffer.Memory.Slice(0, 4));
            buffer.Advance(4);

            BufferExtensions.WriteVector <ushort>(ref buffer, (writer, conn) =>
            {
                state.ResumptionProvider.GenerateSessionTicket(ref writer, conn);
                return(writer);
            }, state);

            BufferExtensions.WriteVector <ushort>(ref buffer, (writer, conn) =>
            {
                writer.WriteBigEndian(ExtensionType.ticket_early_data_info);
                writer.WriteBigEndian <ushort>(sizeof(uint));
                uint maxData = 1024 * 2;
                writer.WriteBigEndian(maxData);
                return(writer);
            }, state);
            return(buffer);
        }
Example #6
0
        public static void ReadCertificates(ReadableBuffer buffer, SecurePipelineListener listener)
        {
            buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize);
            //ignore context
            BufferExtensions.SliceVector <byte>(ref buffer);
            //slice the list
            buffer = BufferExtensions.SliceVector24Bit(ref buffer);
            X509Certificate2Collection collection;

            if (listener.CertificateValidation == null)
            {
                collection = null;
            }
            else
            {
                collection = new X509Certificate2Collection();
            }
            while (buffer.Length > 0)
            {
                var cert = BufferExtensions.SliceVector24Bit(ref buffer);
                var ext  = BufferExtensions.SliceVector <ushort>(ref buffer);
                if (cert.Length > 0 && collection != null)
                {
                    var x509 = new X509Certificate2(cert.ToArray());
                    collection.Add(x509);
                }
            }
            if (collection != null)
            {
                if (!listener.CertificateValidation(collection))
                {
                    Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.bad_certificate, "Failed to verify the certificate chain via the callback");
                }
            }
        }
Example #7
0
 public static void SendFlightOne(ref WritableBuffer writer, IConnectionStateTls13 connectionState)
 {
     connectionState.WriteHandshake(ref writer, HandshakeType.encrypted_extensions, (buffer, state) =>
     {
         BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, state);
         return(buffer);
     });
 }
Example #8
0
 public static void WriteSignatureSchemes(ref WritableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     buffer.WriteBigEndian(ExtensionType.signature_algorithms);
     BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) =>
     {
         connectionState.CryptoProvider.WriteSignatureSchemes(ref writer);
         return(writer);
     }, connectionState);
 }
Example #9
0
 public static void WriteSupportedGroups(ref WritableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     buffer.WriteBigEndian(ExtensionType.supported_groups);
     BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) =>
     {
         connectionState.CryptoProvider.WriteSupportedGroups(ref writer);
         return(writer);
     }, connectionState);
 }
Example #10
0
 public static void WriteServerKeyshare(ref WritableBuffer buffer, IConnectionState connectionState)
 {
     buffer.WriteBigEndian(ExtensionType.key_share);
     BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) =>
     {
         WriteKeyShare(ref writer, state.KeyShare);
         return(writer);
     }, connectionState);
 }
Example #11
0
 public static void ReadSupportedGroups(ReadableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     if (connectionState.KeyShare != null)
     {
         return;
     }
     buffer = BufferExtensions.SliceVector <ushort>(ref buffer);
     connectionState.KeyShare = connectionState.CryptoProvider.GetKeyshareFromNamedGroups(buffer);
 }
Example #12
0
 public static WritableBuffer SendHelloRetry(WritableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     if (connectionState.State == StateType.WaitHelloRetry)
     {
         Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "need to send a hello retry but have already sent one");
     }
     buffer.WriteBigEndian(connectionState.Version);
     BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState);
     return(buffer);
 }
Example #13
0
        public static void ReadKeyshare(ReadableBuffer buffer, IConnectionStateTls13 connectionState)
        {
            if (connectionState.KeyShare?.HasPeerKey == true)
            {
                return;
            }
            buffer = BufferExtensions.SliceVector <ushort>(ref buffer);
            var ks = connectionState.CryptoProvider.GetKeyshareFromKeyshare(buffer);

            connectionState.KeyShare = ks ?? connectionState.KeyShare;
        }
Example #14
0
        public static WritableBuffer SendServerHello13(WritableBuffer buffer, IConnectionStateTls13 connectionState)
        {
            buffer.Ensure(RandomLength + sizeof(ushort));
            buffer.WriteBigEndian(connectionState.Version);
            var memoryToFill = buffer.Memory.Slice(0, RandomLength);

            connectionState.CryptoProvider.FillWithRandom(memoryToFill);
            buffer.Advance(RandomLength);
            buffer.WriteBigEndian(connectionState.CipherSuite.CipherCode);
            BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState);
            return(buffer);
        }
        public static void WriteHandshake(this IConnectionStateTls13 state, ref WritableBuffer writer, HandshakeType handshakeType, Func <WritableBuffer, IConnectionStateTls13, WritableBuffer> contentWriter)
        {
            var dataWritten = writer.BytesWritten;

            writer.WriteBigEndian(handshakeType);
            BufferExtensions.WriteVector24Bit(ref writer, contentWriter, state);
            if (state.HandshakeHash != null)
            {
                var hashBuffer = writer.AsReadableBuffer().Slice(dataWritten);
                state.HandshakeHash.HashData(hashBuffer);
            }
        }
        public static void WriteHandshake <T>(this T state, ref WritableBuffer writer, HandshakeType handshakeType, Func <WritableBuffer, T, WritableBuffer> contentWriter) where T : IConnectionState
        {
            state.Logger?.LogTrace("Writing handshake {handshake type}", handshakeType);
            var dataWritten = writer.BytesWritten;

            writer.WriteBigEndian(handshakeType);
            BufferExtensions.WriteVector24Bit <T>(ref writer, contentWriter, state);
            if (state.HandshakeHash != null)
            {
                var hashBuffer = writer.AsReadableBuffer().Slice(dataWritten);
                state.HandshakeHash.HashData(hashBuffer);
            }
        }
Example #17
0
 public static void WriteClientKeyshares(ref WritableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     buffer.WriteBigEndian(ExtensionType.key_share);
     BufferExtensions.WriteVector <ushort>(ref buffer, (innerWriter, innerState) =>
     {
         BufferExtensions.WriteVector <ushort>(ref innerWriter, (writer, state) =>
         {
             WriteKeyShare(ref writer, state.KeyShare);
             return(writer);
         }, innerState);
         return(innerWriter);
     }, connectionState);
 }
Example #18
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();
         }
     }
 }
Example #19
0
 public static WritableBuffer WriteCertificate(WritableBuffer writer, IConnectionStateTls13 connectionState)
 {
     writer.WriteBigEndian <byte>(0);
     BufferExtensions.WriteVector24Bit(ref writer, (buffer, state) =>
     {
         WriteCertificateEntry(ref buffer, state.Certificate.CertificateData);
         for (int i = 0; i < state.Certificate.CertificateChain.Length; i++)
         {
             WriteCertificateEntry(ref buffer, state.Certificate.CertificateChain[i]);
         }
         return(buffer);
     }, connectionState);
     return(writer);
 }
Example #20
0
        public static WritableBuffer SendCertificates(WritableBuffer buffer, IConnectionStateTls12 connectionState)
        {
            var startOfMessage = buffer.BytesWritten;

            BufferExtensions.WriteVector24Bit(ref buffer, (writer, state) =>
            {
                WriteCertificateEntry(ref writer, connectionState.Certificate.CertificateData);
                foreach (var b in connectionState.Certificate.CertificateChain)
                {
                    WriteCertificateEntry(ref writer, b);
                }
                return(buffer);
            }, connectionState);
            return(buffer);
        }
Example #21
0
 public static WritableBuffer WriteClientHello(WritableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     buffer.WriteBigEndian <ushort>(0x0303);
     buffer.Ensure(RandomLength);
     connectionState.CryptoProvider.FillWithRandom(buffer.Memory.Slice(0, RandomLength));
     buffer.Advance(RandomLength);
     //legacy sessionid
     buffer.WriteBigEndian((byte)0);
     connectionState.CryptoProvider.WriteCipherSuites(ref buffer);
     //legacy compression
     buffer.WriteBigEndian((byte)1);
     buffer.WriteBigEndian((byte)0);
     connectionState.KeyShare = connectionState.CryptoProvider.GetDefaultKeyShare();
     BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState);
     return(buffer);
 }
Example #22
0
 public static void ReadSignatureScheme(ReadableBuffer buffer, IConnectionState connectionState)
 {
     buffer = BufferExtensions.SliceVector <ushort>(ref buffer);
     while (buffer.Length > 1)
     {
         SignatureScheme scheme;
         buffer = buffer.SliceBigEndian(out scheme);
         var cert = connectionState.CertificateList.GetCertificate(connectionState.ServerName, scheme);
         if (cert != null)
         {
             connectionState.Certificate     = cert;
             connectionState.SignatureScheme = scheme;
             return;
         }
     }
     Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.handshake_failure, "Failed to find a signature scheme that matches");
 }
Example #23
0
 public static void ReadPskKeyExchangeMode(ReadableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     buffer = BufferExtensions.SliceVector <byte>(ref buffer);
     while (buffer.Length > 0)
     {
         PskKeyExchangeMode mode;
         buffer = buffer.SliceBigEndian(out mode);
         if (connectionState.PskKeyExchangeMode == PskKeyExchangeMode.none)
         {
             connectionState.PskKeyExchangeMode = mode;
         }
         else
         {
             connectionState.PskKeyExchangeMode |= mode;
         }
     }
 }
Example #24
0
        public static void ReadClientHello(ref ReadableBuffer readable, IConnectionState connectionState)
        {
            readable = readable.Slice(HandshakeProcessor.HandshakeHeaderSize);
            readable = readable.Slice(sizeof(ushort));
            connectionState.SetClientRandom(readable.Slice(0, RandomLength));
            readable = readable.Slice(RandomLength);
            //We don't support sessions via id so slice and throw
            BufferExtensions.SliceVector <byte>(ref readable);
            //Slice Cipher Suite
            var ciphers = BufferExtensions.SliceVector <ushort>(ref readable);

            if (connectionState.CipherSuite == null)
            {
                connectionState.CipherSuite = connectionState.CryptoProvider.GetCipherSuiteFromExtension(ciphers, connectionState.Version);
            }
            //Skip compression
            BufferExtensions.SliceVector <byte>(ref readable);
        }
Example #25
0
        public override byte[] Write()
        {
            var extras = CreateExtras();
            var key    = CreateKey();
            var body   = CreateBody();
            var header = CreateHeader(extras, body, key);

            var buffer = new byte[BufferExtensions.GetLengthSafe(extras) +
                                  BufferExtensions.GetLengthSafe(body) +
                                  BufferExtensions.GetLengthSafe(key) +
                                  BufferExtensions.GetLengthSafe(header)];

            System.Buffer.BlockCopy(header, 0, buffer, 0, header.Length);
            System.Buffer.BlockCopy(extras, 0, buffer, header.Length, extras.Length);
            System.Buffer.BlockCopy(key, 0, buffer, header.Length + extras.Length, key.Length);
            System.Buffer.BlockCopy(body, 0, buffer, header.Length + extras.Length + key.Length, body.Length);

            return(buffer);
        }
Example #26
0
        public static TlsVersion ReadSupportedVersion(ReadableBuffer buffer, TlsVersion[] supportedVersions)
        {
            TlsVersion returnVersion = 0;

            buffer = BufferExtensions.SliceVector <byte>(ref buffer);
            while (buffer.Length > 1)
            {
                TlsVersion version;
                buffer = buffer.SliceBigEndian(out version);
                if (supportedVersions.Contains(version))
                {
                    if (version > returnVersion)
                    {
                        returnVersion = version;
                    }
                }
            }
            return(returnVersion);
        }
        // Fix some incorrect ines header entries that QuickNES uses to load games.
        // we need to do this from the raw file since QuickNES hasn't had time to process it yet.
        private byte[] FixInesHeader(byte[] file)
        {
            string sha1         = BufferExtensions.HashSHA1(file);
            bool   didSomething = false;

            Console.WriteLine(sha1);
            if (sha1 == "93010514AA1300499ABC8F145D6ABCDBF3084090")            // Ms. Pac Man (Tengen) [!]
            {
                file[6]     &= 0xFE;
                didSomething = true;
            }

            if (didSomething)
            {
                Console.WriteLine("iNES header error detected, adjusting settings...");
                Console.WriteLine(sha1);
            }

            return(file);
        }
Example #28
0
        private static TlsVersion GetVersion(ref ReadableBuffer buffer)
        {
            //Jump the version header and the randoms
            buffer = buffer.Slice(HandshakeProcessor.HandshakeHeaderSize);
            TlsVersion version;

            buffer = buffer.SliceBigEndian(out version);
            if (!_supportedVersion.Contains(version))
            {
                Alerts.AlertException.ThrowAlert(Alerts.AlertLevel.Fatal, Alerts.AlertDescription.protocol_version, $"The version was not in the supported list {version}");
            }
            //Slice out the random
            buffer = buffer.Slice(Hello.RandomLength);
            //No sessions slice and dump
            BufferExtensions.SliceVector <byte>(ref buffer);
            //Skip the cipher suites if we find a version we are happy with
            //then the cipher suite is dealt with by that version
            BufferExtensions.SliceVector <ushort>(ref buffer);
            //Skip compression, we don't care about that either, we just want to get to the end
            BufferExtensions.SliceVector <byte>(ref buffer);
            //And here we are at the end, if we have no extensions then we must be the header version that
            //we accepted earlier
            if (buffer.Length == 0)
            {
                return(version);
            }
            buffer = BufferExtensions.SliceVector <ushort>(ref buffer);
            while (buffer.Length >= 8)
            {
                ExtensionType type;
                buffer = buffer.SliceBigEndian(out type);
                var ext = BufferExtensions.SliceVector <ushort>(ref buffer);
                if (type == ExtensionType.supported_versions)
                {
                    //Scan the version for supported ones
                    return(ExtensionsRead.ReadSupportedVersion(ext, _supportedVersion));
                }
            }
            return(version);
        }
Example #29
0
        public static void ReadPskKey(ReadableBuffer pskBuffer, IConnectionStateTls13 connectionState)
        {
            var identities = BufferExtensions.SliceVector <ushort>(ref pskBuffer);

            while (identities.Length > 0)
            {
                var  identity = BufferExtensions.SliceVector <ushort>(ref identities);
                long serviceId, keyId;
                identity = identity.SliceBigEndian(out serviceId);
                identity = identity.SliceBigEndian(out keyId);
                int ticketAge;
                identities = identities.SliceBigEndian(out ticketAge);
                if (!connectionState.ResumptionProvider.TryToResume(serviceId, keyId, identity, connectionState))
                {
                    continue;
                }
                if ((connectionState.PskKeyExchangeMode & PskKeyExchangeMode.psk_dhe_ke) == 0)
                {
                    connectionState.KeyShare?.Dispose();
                    connectionState.KeyShare = null;
                }
                return;
            }
        }
Example #30
0
        private void Receive(IAsyncResult ar)
        {
            var receivedBytes = 0;

            try
            {
                receivedBytes = _socket.EndReceive(ar);
            }
            catch (Exception ex)
            {
                Disconnect($"Receive Exception: {ex}");
            }

            // Check if the socket was closed.
            if (receivedBytes == 0)
            {
                Disconnect();
                return;
            }

            // Check the message header.
            if (receivedBytes < InHeaderSize)
            {
                Disconnect("The received packets header size is incorrect.");
                return;
            }

            // TODO Properly Process incomming bytes.
            using (var stream = new MemoryStream(_receiveBuffer, 0, receivedBytes))
                using (var reader = new BinaryReader(stream))
                {
                    var size      = reader.ReadUInt16();
                    var encrypted = reader.ReadByte() == 1;

                    var body = reader.ReadBytes(size - InHeaderSize);

                    if (encrypted)
                    {
                        body = BDOCrypt.Xor(body, 0, body.Length);
                    }

                    using (var messageStream = new MemoryStream(body))
                        using (var message = new BinaryReader(messageStream))
                        {
                            var messageId = message.ReadUInt16(); // MessageId

                            Logging.Server($"Received(Size:{size}, Encrypted: {encrypted}, MessageId: {messageId}, 0x{messageId:X2})");
                            //Logging.Server(BufferExtensions.ToHex(body.Skip(2).ToArray()));

                            var handler = MessageTable.FindMessageHandler(messageId);

                            if (handler != null)
                            {
                                handler.Handle(this, message);
                            }
                            else
                            {
                                Logging.Server($"Unknown Message Received: Size:{size}, Encrypted: {encrypted}, MessageId: {messageId} (0x{messageId:X2})");
                                Logging.Server(BufferExtensions.ToHex(body.Skip(2).ToArray()));
                            }
                        }
                }

            // Start receiving more data.
            BeginReceive();
        }