#include "ShannonConnection.h" #include "Logger.h" ShannonConnection::ShannonConnection() { } ShannonConnection::~ShannonConnection() { } void ShannonConnection::wrapConnection(std::shared_ptr conn, std::vector &sendKey, std::vector &recvKey) { this->conn = conn; this->sendCipher = std::make_unique(); this->recvCipher = std::make_unique(); // Set keys this->sendCipher->key(sendKey); this->recvCipher->key(recvKey); // Set initial nonce this->sendCipher->nonce(pack(htonl(0))); this->recvCipher->nonce(pack(htonl(0))); } void ShannonConnection::sendPacket(uint8_t cmd, std::vector &data) { this->writeMutex.lock(); auto rawPacket = this->cipherPacket(cmd, data); // Shannon encrypt the packet and write it to sock this->sendCipher->encrypt(rawPacket); this->conn->writeBlock(rawPacket); // Generate mac std::vector mac(MAC_SIZE); this->sendCipher->finish(mac); // Update the nonce this->sendNonce += 1; this->sendCipher->nonce(pack(htonl(this->sendNonce))); // Write the mac to sock this->conn->writeBlock(mac); this->writeMutex.unlock(); } std::unique_ptr ShannonConnection::recvPacket() { this->readMutex.lock(); // Receive 3 bytes, cmd + int16 size auto data = this->conn->readBlock(3); this->recvCipher->decrypt(data); auto packetData = std::vector(); auto readSize = ntohs(extract(data, 1)); // Read and decode if the packet has an actual body if (readSize > 0) { packetData = this->conn->readBlock(readSize); this->recvCipher->decrypt(packetData); } // Read mac auto mac = this->conn->readBlock(MAC_SIZE); // Generate mac std::vector mac2(MAC_SIZE); this->recvCipher->finish(mac2); if (mac != mac2) { CSPOT_LOG(error, "Shannon read: Mac doesn't match"); } // Update the nonce this->recvNonce += 1; this->recvCipher->nonce(pack(htonl(this->recvNonce))); // Unlock the mutex this->readMutex.unlock(); // data[0] == cmd return std::make_unique(data[0], packetData); } std::vector ShannonConnection::cipherPacket(uint8_t cmd, std::vector &data) { // Generate packet structure, [Command] [Size] [Raw data] auto sizeRaw = pack(htons(uint16_t(data.size()))); sizeRaw.insert(sizeRaw.begin(), cmd); sizeRaw.insert(sizeRaw.end(), data.begin(), data.end()); return sizeRaw; }