CovertProtocolBidirectional.hpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #ifndef COVERTPROTOCOLBIDIRECTIONAL_H
  2. #define COVERTPROTOCOLBIDIRECTIONAL_H
  3. #include <fstream>
  4. #include <string>
  5. #include <type_traits>
  6. #include "../ChannelControls.h"
  7. #include "CovertProtocol.hpp"
  8. /**
  9. * @class CovertProtocolBidirectional
  10. *
  11. * A bidirectional Covert Channel protocol with a variable size template.
  12. *
  13. * The protocol works bidirectional so the active side uses send to encode data to be sent and the passive side uses receive to extract data. And the passive
  14. * side uses send to send ACKs and and the active side uses receive to receive ACKs.
  15. *
  16. * @param N number of bytes which can be used to transmit data
  17. * @param PASSIVE passive mode
  18. */
  19. template <int N, bool PASSIVE> class CovertProtocolBidirectional : public ChannelControls {
  20. static_assert(N >= 2);
  21. public:
  22. /**
  23. * CovertProtocolBidirectional constructor
  24. */
  25. CovertProtocolBidirectional() : segment(PASSIVE ? 1 : 0) {
  26. lastData = new uint8_t[N]();
  27. protocol.reset();
  28. }
  29. /**
  30. * CovertProtocol destructor
  31. */
  32. ~CovertProtocolBidirectional() { delete[](lastData); }
  33. /**
  34. * send encodes the data into the data array
  35. *
  36. * @param data must be an array of size N
  37. */
  38. void send(uint8_t *const data) {
  39. if (sendResetFlag) {
  40. sendResetFlag = false;
  41. data[0] = (segment << 6) | 1;
  42. std::memset(data + 1, 0, N - 1);
  43. return;
  44. }
  45. if (sendSegment()) {
  46. std::memcpy(data, lastData, N);
  47. return;
  48. }
  49. if constexpr (!PASSIVE) {
  50. protocol.send(data + 1);
  51. }
  52. data[0] = (segment << 6);
  53. // save data to lastData
  54. std::memcpy(lastData, data, N);
  55. }
  56. /**
  57. * receive extracts data from the data array
  58. *
  59. * @param data must be an array of size N
  60. */
  61. void receive(const uint8_t *const data) {
  62. uint8_t seg = data[0] >> 6;
  63. bool reset = data[0] & 1;
  64. if (reset) {
  65. resetState();
  66. return;
  67. }
  68. if (receiveSegment(seg)) {
  69. return;
  70. }
  71. if constexpr (PASSIVE) {
  72. protocol.receive(data + 1);
  73. }
  74. }
  75. /* ChannelControls */
  76. /**
  77. * Starts sending a file.
  78. *
  79. * Starts sending a file if no transmission is running and the file exists.
  80. *
  81. * @param fileName name of the file in the file directory
  82. * @return true - file will be sent | false - file was not accepted
  83. */
  84. virtual bool sendFile(const std::string &fileName) { return protocol.sendFile(fileName); }
  85. /**
  86. * Get the progress
  87. *
  88. * @return progress counters
  89. */
  90. virtual std::pair<uint32_t, uint32_t> getProgress() { return protocol.getProgress(); }
  91. /**
  92. * Test if a transfer is running
  93. *
  94. * @return true - a transfer runs | false - no transfer runs
  95. */
  96. virtual bool isTransferRunning() { return protocol.isTransferRunning(); }
  97. /**
  98. * Resets state and sets reset flag so a reset signal is sent in the next packet
  99. */
  100. virtual void reset() {
  101. sendResetFlag = true;
  102. resetState();
  103. }
  104. /**
  105. * Test if a transfer is running
  106. *
  107. * @return true - a transfer runs | false - no transfer runs
  108. */
  109. virtual std::time_t getTransferStart() { return protocol.getTransferStart(); }
  110. /**
  111. * Get file name of the file which is currently be sent or received.
  112. *
  113. * @return file name
  114. */
  115. virtual std::string getFileName() { return protocol.getFileName(); };
  116. /* =============== */
  117. private:
  118. /**
  119. * current segment counter
  120. */
  121. uint8_t segment;
  122. /**
  123. * last acknowledged segment counter
  124. */
  125. uint8_t lastACKedSegment = 0;
  126. /**
  127. * lastData sent
  128. */
  129. uint8_t *lastData;
  130. /**
  131. * Simple protocol
  132. */
  133. CovertProtocol<N - 1, PASSIVE> protocol;
  134. /**
  135. * Sends a reset signal on next send call
  136. */
  137. bool sendResetFlag = true;
  138. /**
  139. * Evaluates received segment number and increases own segment number if necessary
  140. *
  141. * @param seg received segment number
  142. * @return true if segment should discarded
  143. */
  144. inline bool receiveSegment(uint8_t seg) {
  145. if constexpr (PASSIVE) {
  146. if (seg == segment && seg == increaseSegment(lastACKedSegment, 1)) {
  147. lastACKedSegment = seg;
  148. return false;
  149. } else {
  150. return true;
  151. }
  152. } else {
  153. if (seg == increaseSegment(segment, 1) && seg == increaseSegment(lastACKedSegment, 2)) {
  154. lastACKedSegment = increaseSegment(lastACKedSegment, 1);
  155. return false;
  156. } else {
  157. return true;
  158. }
  159. }
  160. }
  161. /**
  162. * Returns true if the segment should be repeated.
  163. *
  164. * @return true if segment should be repeated
  165. */
  166. inline bool sendSegment() {
  167. if (segment == lastACKedSegment) {
  168. segment = increaseSegment(segment, 1);
  169. return false;
  170. } else {
  171. return true;
  172. }
  173. }
  174. /**
  175. * Calculates seg + inc
  176. * @return seg + inc
  177. */
  178. inline uint8_t increaseSegment(uint8_t seg, uint8_t inc) { return seg + inc & 0x3; }
  179. /**
  180. * Resets the state of the protocol.
  181. * This method can / should only be called from this class.
  182. */
  183. void resetState() {
  184. protocol.reset();
  185. segment = (PASSIVE ? 1 : 0);
  186. lastACKedSegment = 0;
  187. std::memset(lastData, 0, N);
  188. }
  189. };
  190. #endif