From e735faf7558aff457432a14bdfde893b33d4d311 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 28 Jun 2021 22:12:01 +0100 Subject: [PATCH] Protocol: call the encryptor once before sending data --- src/ClientHandle.cpp | 1 + src/Protocol/Protocol.h | 10 ++++--- src/Protocol/Protocol_1_8.cpp | 45 ++++++++++------------------ src/Protocol/Protocol_1_8.h | 8 ++--- src/mbedTLS++/AesCfb128Encryptor.cpp | 4 +-- src/mbedTLS++/AesCfb128Encryptor.h | 10 ++----- 6 files changed, 30 insertions(+), 48 deletions(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 2e50c669b..8dbf4faa5 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -238,6 +238,7 @@ void cClientHandle::ProcessProtocolOut() // to prevent it being reset between the null check and the Send: if (auto Link = m_Link; Link != nullptr) { + m_Protocol->DataPrepared(OutgoingData); Link->Send(OutgoingData.data(), OutgoingData.size()); } } diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 334d8d56b..de420308b 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -346,10 +346,15 @@ public: Game = 3, }; - /** Called to process them, when client sends some data. + /** Called by cClientHandle to process data, when the client sends some. The protocol uses the provided buffers for storage and processing, and must have exclusive access to them. */ virtual void DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer && a_Data) = 0; + /** Called by cClientHandle to finalise a buffer of prepared data before they are sent to the client. + Descendants may for example, encrypt the data if needed. + The protocol modifies the provided buffer in-place. */ + virtual void DataPrepared(ContiguousByteBuffer & a_Data) = 0; + // Sending stuff to clients (alphabetically sorted): virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) = 0; virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) = 0; @@ -466,9 +471,6 @@ protected: /** Returns the current protocol's version, for handling status requests. */ virtual Version GetProtocolVersion() const = 0; - /** A generic data-sending routine, all outgoing packet data needs to be routed through this so that descendants may override it. */ - virtual void SendData(ContiguousByteBufferView a_Data) = 0; - /** Sends a single packet contained within the cPacketizer class. The cPacketizer's destructor calls this to send the contained packet; protocol may transform the data (compression in 1.8 etc). */ virtual void SendPacket(cPacketizer & a_Packet) = 0; diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index 5c8ffd5df..205a899c1 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -188,6 +188,18 @@ void cProtocol_1_8_0::DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer +void cProtocol_1_8_0::DataPrepared(ContiguousByteBuffer & a_Data) +{ + if (m_IsEncrypted) + { + m_Encryptor.ProcessData(a_Data.data(), a_Data.size()); + } +} + + + + + void cProtocol_1_8_0::SendAttachEntity(const cEntity & a_Entity, const cEntity & a_Vehicle) { ASSERT(m_State == 3); // In game mode? @@ -370,7 +382,7 @@ void cProtocol_1_8_0::SendChunkData(const ContiguousByteBufferView a_ChunkData) ASSERT(m_State == 3); // In game mode? cCSLock Lock(m_CSPacket); - SendData(a_ChunkData); + m_Client->SendData(a_ChunkData); } @@ -3003,31 +3015,6 @@ void cProtocol_1_8_0::SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_Ob -void cProtocol_1_8_0::SendData(ContiguousByteBufferView a_Data) -{ - if (m_IsEncrypted) - { - std::byte Encrypted[8 KiB]; // Larger buffer, we may be sending lots of data (chunks) - - while (a_Data.size() > 0) - { - const auto NumBytes = (a_Data.size() > sizeof(Encrypted)) ? sizeof(Encrypted) : a_Data.size(); - m_Encryptor.ProcessData(Encrypted, a_Data.data(), NumBytes); - m_Client->SendData({ Encrypted, NumBytes }); - - a_Data = a_Data.substr(NumBytes); - } - } - else - { - m_Client->SendData(a_Data); - } -} - - - - - void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) { ASSERT(m_OutPacketBuffer.GetReadableSpace() == m_OutPacketBuffer.GetUsedSpace()); @@ -3045,7 +3032,7 @@ void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) cProtocol_1_8_0::CompressPacket(m_Compressor, CompressedPacket); // Send the packet's payload compressed: - SendData(CompressedPacket); + m_Client->SendData(CompressedPacket); } else { @@ -3054,10 +3041,10 @@ void cProtocol_1_8_0::SendPacket(cPacketizer & a_Pkt) ContiguousByteBuffer LengthData; m_OutPacketLenBuffer.ReadAll(LengthData); m_OutPacketLenBuffer.CommitRead(); - SendData(LengthData); + m_Client->SendData(LengthData); // Send the packet's payload directly: - SendData(PacketData); + m_Client->SendData(PacketData); } // Log the comm into logfile: diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index b1157366b..838435ad0 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -36,11 +36,10 @@ public: cProtocol_1_8_0(cClientHandle * a_Client, const AString & a_ServerAddress, State a_State); - /** Called to process them, when client sends some data. - The protocol uses the provided buffers for storage and processing, and must have exclusive access to them. */ virtual void DataReceived(cByteBuffer & a_Buffer, ContiguousByteBuffer && a_Data) override; + virtual void DataPrepared(ContiguousByteBuffer & a_Data) override; - /** Sending stuff to clients (alphabetically sorted): */ + // Sending stuff to clients (alphabetically sorted): virtual void SendAttachEntity (const cEntity & a_Entity, const cEntity & a_Vehicle) override; virtual void SendBlockAction (int a_BlockX, int a_BlockY, int a_BlockZ, char a_Byte1, char a_Byte2, BLOCKTYPE a_BlockType) override; virtual void SendBlockBreakAnim (UInt32 a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override; @@ -216,9 +215,6 @@ protected: /** Sends the entity type and entity-dependent data required for the entity to initially spawn. */ virtual void SendEntitySpawn(const cEntity & a_Entity, const UInt8 a_ObjectType, const Int32 a_ObjectData); - /** Sends the data to the client, encrypting them if needed. */ - virtual void SendData(ContiguousByteBufferView a_Size) override; - /** Sends the packet to the client. Called by the cPacketizer's destructor. */ virtual void SendPacket(cPacketizer & a_Packet) override; diff --git a/src/mbedTLS++/AesCfb128Encryptor.cpp b/src/mbedTLS++/AesCfb128Encryptor.cpp index 7c2ae8b2b..2a08ef28e 100644 --- a/src/mbedTLS++/AesCfb128Encryptor.cpp +++ b/src/mbedTLS++/AesCfb128Encryptor.cpp @@ -43,8 +43,8 @@ void cAesCfb128Encryptor::Init(const Byte a_Key[16], const Byte a_IV[16]) -void cAesCfb128Encryptor::ProcessData(std::byte * const a_EncryptedOut, const std::byte * const a_PlainIn, size_t a_Length) +void cAesCfb128Encryptor::ProcessData(std::byte * const a_PlainIn, const size_t a_Length) { ASSERT(IsValid()); // Must Init() first - mbedtls_aes_crypt_cfb8(&m_Aes, MBEDTLS_AES_ENCRYPT, a_Length, m_IV, reinterpret_cast(a_PlainIn), reinterpret_cast(a_EncryptedOut)); + mbedtls_aes_crypt_cfb8(&m_Aes, MBEDTLS_AES_ENCRYPT, a_Length, m_IV, reinterpret_cast(a_PlainIn), reinterpret_cast(a_PlainIn)); } diff --git a/src/mbedTLS++/AesCfb128Encryptor.h b/src/mbedTLS++/AesCfb128Encryptor.h index f25998c15..ce3e1fd56 100644 --- a/src/mbedTLS++/AesCfb128Encryptor.h +++ b/src/mbedTLS++/AesCfb128Encryptor.h @@ -26,13 +26,14 @@ public: /** Initializes the decryptor with the specified Key / IV */ void Init(const Byte a_Key[16], const Byte a_IV[16]); - /** Encrypts a_Length bytes of the plain data; produces a_Length output bytes */ - void ProcessData(std::byte * a_EncryptedOut, const std::byte * a_PlainIn, size_t a_Length); + /** Encrypts a_Length bytes of the plain data in-place; produces a_Length output bytes */ + void ProcessData(std::byte * a_PlainIn, size_t a_Length); /** Returns true if the object has been initialized with the Key / IV */ bool IsValid(void) const { return m_IsValid; } protected: + mbedtls_aes_context m_Aes; /** The InitialVector, used by the CFB mode encryption */ @@ -41,8 +42,3 @@ protected: /** Indicates whether the object has been initialized with the Key / IV */ bool m_IsValid; } ; - - - - -