From e5c041876000089b650307105183da65322cd5ae Mon Sep 17 00:00:00 2001 From: study-faraphel Date: Wed, 20 Nov 2024 15:24:14 +0100 Subject: [PATCH] base for packet encryption --- CMakeLists.txt | 1 - source/packets/base/Packet.cpp | 52 ++++++++++++++++++++------- source/packets/base/Packet.hpp | 25 +++++++++---- source/packets/base/PacketContent.cpp | 41 ++++++++++++++------- source/utils/CacheMap.hpp | 35 ------------------ 5 files changed, 87 insertions(+), 67 deletions(-) delete mode 100644 source/utils/CacheMap.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 16d777a..73a3494 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,6 @@ add_executable(M2-PT-DRP source/behavior/tasks/client/ClientTask.cpp source/behavior/tasks/client/ClientTask.hpp source/Context.hpp - source/utils/CacheMap.hpp source/packets/search/SearchPacketData.hpp source/packets/base/PacketContent.cpp source/packets/base/PacketContent.hpp diff --git a/source/packets/base/Packet.cpp b/source/packets/base/Packet.cpp index c80a2ac..713de01 100644 --- a/source/packets/base/Packet.cpp +++ b/source/packets/base/Packet.cpp @@ -1,6 +1,7 @@ #include "Packet.hpp" #include +#include #include "SecurityMode.hpp" @@ -49,23 +50,50 @@ GenericPacketContent decryptPacketContentAes(const GenericPacket& packet) { */ -PacketContent Packet::getContent() const { - // TODO(Faraphel): implement RSA and AES - // additional "context" argument to hold cryptographic keys ? +inline Packet::Packet( + const Context& context, + const std::uint8_t channel, + SecurityMode securityMode, + const PacketContent& content +) { + this->channel = channel; + this->securityMode = static_cast(securityMode); + + switch (securityMode) { + case SecurityMode::PLAIN: + this->content = static_cast(content); + break; + case SecurityMode::RSA: + this->content = encryptRsa(context, content); + break; + case SecurityMode::AES: + this->content = encryptAes(context, content); + break; + default: + throw std::invalid_argument("Invalid security mode."); + } +} + + +PacketContent Packet::getContent( + const Context& context, + const sockaddr_storage& address, + socklen_t addressLength +) const { + PacketContent content {}; switch (static_cast(this->securityMode)) { case SecurityMode::PLAIN: - return this->_content; - - case SecurityMode::AES: - // return decryptPacketContentAes(packet); - throw std::runtime_error("Not implemented."); - + std::memcpy(&content, &this->content, sizeof(PacketContent)); + return content; case SecurityMode::RSA: - throw std::runtime_error("Not implemented."); - + content = decryptRsa(context, this->content, address, addressLength); + return content; + case SecurityMode::AES: + content = decryptAes(context, this->content); + return content; default: - throw std::runtime_error("Unsupported security mode."); + throw std::invalid_argument("Invalid security mode."); } } diff --git a/source/packets/base/Packet.hpp b/source/packets/base/Packet.hpp index fa6352c..d305279 100644 --- a/source/packets/base/Packet.hpp +++ b/source/packets/base/Packet.hpp @@ -3,7 +3,9 @@ #include #include +#include "Context.hpp" #include "PacketContent.hpp" +#include "SecurityMode.hpp" namespace drp::packet::base { @@ -14,15 +16,26 @@ namespace drp::packet::base { * @param channel the channel of the packet. Two system can be created inside a same network by using different * channels value. "0" is used for "broadcast" message across networks. * @param securityMode the type of security used in the packet. - * @param _content the content of the packet. It is encrypted accordingly to the securityMode. + * @param content the content of the packet. It is encrypted accordingly to the securityMode. */ -struct Packet { +class Packet { +public: + explicit Packet( + const Context& context, + std::uint8_t channel, + SecurityMode securityMode, + const PacketContent& content + ); + [[nodiscard]] PacketContent getContent( + const Context& context, + const sockaddr_storage& address, + socklen_t addressLength + ) const; + +private: std::uint8_t channel; std::uint8_t securityMode; - PacketContent _content; - - [[nodiscard]] PacketContent getContent() const; - void setContent(const PacketContent& content); + std::array content; }; diff --git a/source/packets/base/PacketContent.cpp b/source/packets/base/PacketContent.cpp index cfa3cdd..42b34b5 100644 --- a/source/packets/base/PacketContent.cpp +++ b/source/packets/base/PacketContent.cpp @@ -1,7 +1,10 @@ #include "PacketContent.hpp" #include +#include +#include +#include "Context.hpp" #include "Packet.hpp" #include "SecurityMode.hpp" @@ -9,22 +12,34 @@ namespace drp::packet::base { -void Packet::setContent(const PacketContent &content) { - // TODO(Faraphel): implement RSA and AES - switch (static_cast(this->securityMode)) { - case SecurityMode::PLAIN: - this->_content = content; - return; +void PacketContent::encryptRsa(const std::array& publicKey) { + BIO* bioPublicKey = BIO_new_mem_buf(publicKey.data(), static_cast(publicKey.size())); + EVP_PKEY* evpPublicKey = PEM_read_bio_PUBKEY(bioPublicKey, nullptr, nullptr, nullptr); - case SecurityMode::AES: - throw std::runtime_error("Not implemented."); + const std::unique_ptr evpContext( + EVP_PKEY_CTX_new(evpPublicKey, nullptr), + EVP_PKEY_CTX_free + ); + if (evpContext == nullptr) + throw std::runtime_error("Failed to create EVP_PKEY_CTX"); - case SecurityMode::RSA: - throw std::runtime_error("Not implemented."); + if (EVP_PKEY_encrypt_init(evpContext.get()) <= 0) + throw std::runtime_error("Failed to initialize EVP_PKEY_CTX"); + + if (EVP_PKEY_CTX_set_rsa_padding(evpContext.get(), RSA_PKCS1_PADDING) <= 0) + throw std::runtime_error("Failed to set RSA_PKCS1_PADDING"); + + std::vector cipher(EVP_PKEY_size(evpPublicKey)); + std::size_t cipherLength; + EVP_PKEY_encrypt( + evpContext.get(), + cipher.data(), + &cipherLength, + this, + sizeof(*this) + ); + cipher.resize(cipherLength); - default: - throw std::runtime_error("Unsupported security mode."); - } } diff --git a/source/utils/CacheMap.hpp b/source/utils/CacheMap.hpp deleted file mode 100644 index 9d980ea..0000000 --- a/source/utils/CacheMap.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include - - -namespace drp::util { - - -template> -class CacheMap : std::map { -public: - void cache() { - // check if the limit have been reached. - if (this->size() <= limit) - return; - - // apply the comparator on all the value to find the minimum. - auto minimum = this->begin(); - for (const auto& it : this) - if (Comparator()(it.second, minimum)) - minimum = it; - - // delete this lowest value. - this->erase(minimum); - } - - Value& operator[](const Key& key) { - const auto& value = std::map::operator[](key); - this->cache(); - return value; - } -}; - - -}