ShannonConnection.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "ShannonConnection.h"
  2. #include <type_traits> // for remove_extent_t
  3. #include "BellLogger.h" // for AbstractLogger
  4. #include "Logger.h" // for CSPOT_LOG
  5. #include "Packet.h" // for Packet, cspot
  6. #include "PlainConnection.h" // for PlainConnection
  7. #include "Shannon.h" // for Shannon
  8. #include "Utils.h" // for pack, extract
  9. #ifndef _WIN32
  10. #include <arpa/inet.h>
  11. #endif
  12. using namespace cspot;
  13. ShannonConnection::ShannonConnection() {}
  14. ShannonConnection::~ShannonConnection() {}
  15. void ShannonConnection::wrapConnection(
  16. std::shared_ptr<cspot::PlainConnection> conn, std::vector<uint8_t>& sendKey,
  17. std::vector<uint8_t>& recvKey) {
  18. this->conn = conn;
  19. this->sendCipher = std::make_unique<Shannon>();
  20. this->recvCipher = std::make_unique<Shannon>();
  21. // Set keys
  22. this->sendCipher->key(sendKey);
  23. this->recvCipher->key(recvKey);
  24. // Set initial nonce
  25. this->sendCipher->nonce(pack<uint32_t>(htonl(0)));
  26. this->recvCipher->nonce(pack<uint32_t>(htonl(0)));
  27. }
  28. void ShannonConnection::sendPacket(uint8_t cmd, std::vector<uint8_t>& data) {
  29. std::scoped_lock lock(this->writeMutex);
  30. auto rawPacket = this->cipherPacket(cmd, data);
  31. // Shannon encrypt the packet and write it to sock
  32. this->sendCipher->encrypt(rawPacket);
  33. this->conn->writeBlock(rawPacket);
  34. // Generate mac
  35. std::vector<uint8_t> mac(MAC_SIZE);
  36. this->sendCipher->finish(mac);
  37. // Update the nonce
  38. this->sendNonce += 1;
  39. this->sendCipher->nonce(pack<uint32_t>(htonl(this->sendNonce)));
  40. // Write the mac to sock
  41. this->conn->writeBlock(mac);
  42. }
  43. cspot::Packet ShannonConnection::recvPacket() {
  44. std::scoped_lock lock(this->readMutex);
  45. std::vector<uint8_t> data(3);
  46. // Receive 3 bytes, cmd + int16 size
  47. this->conn->readBlock(data.data(), 3);
  48. this->recvCipher->decrypt(data);
  49. auto readSize = ntohs(extract<uint16_t>(data, 1));
  50. auto packetData = std::vector<uint8_t>(readSize);
  51. // Read and decode if the packet has an actual body
  52. if (readSize > 0) {
  53. this->conn->readBlock(packetData.data(), readSize);
  54. this->recvCipher->decrypt(packetData);
  55. }
  56. // Read mac
  57. std::vector<uint8_t> mac(MAC_SIZE);
  58. this->conn->readBlock(mac.data(), MAC_SIZE);
  59. // Generate mac
  60. std::vector<uint8_t> mac2(MAC_SIZE);
  61. this->recvCipher->finish(mac2);
  62. if (mac != mac2) {
  63. CSPOT_LOG(error, "Shannon read: Mac doesn't match");
  64. }
  65. // Update the nonce
  66. this->recvNonce += 1;
  67. this->recvCipher->nonce(pack<uint32_t>(htonl(this->recvNonce)));
  68. uint8_t cmd = 0;
  69. if (data.size() > 0) {
  70. cmd = data[0];
  71. }
  72. // data[0] == cmd
  73. return Packet{cmd, packetData};
  74. }
  75. std::vector<uint8_t> ShannonConnection::cipherPacket(
  76. uint8_t cmd, std::vector<uint8_t>& data) {
  77. // Generate packet structure, [Command] [Size] [Raw data]
  78. auto sizeRaw = pack<uint16_t>(htons(uint16_t(data.size())));
  79. sizeRaw.insert(sizeRaw.begin(), cmd);
  80. sizeRaw.insert(sizeRaw.end(), data.begin(), data.end());
  81. return sizeRaw;
  82. }