ShannonConnection.cpp 2.5 KB

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