TunnelConfig.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #ifndef TUNNEL_CONFIG_H__
  2. #define TUNNEL_CONFIG_H__
  3. #include <inttypes.h>
  4. #include <sstream>
  5. #include <vector>
  6. #include <memory>
  7. #include "Identity.h"
  8. #include "RouterContext.h"
  9. #include "Timestamp.h"
  10. namespace i2p
  11. {
  12. namespace tunnel
  13. {
  14. struct TunnelHopConfig
  15. {
  16. std::shared_ptr<const i2p::data::IdentityEx> ident;
  17. i2p::data::IdentHash nextIdent;
  18. uint32_t tunnelID, nextTunnelID;
  19. uint8_t layerKey[32];
  20. uint8_t ivKey[32];
  21. uint8_t replyKey[32];
  22. uint8_t replyIV[16];
  23. bool isGateway, isEndpoint;
  24. TunnelHopConfig * next, * prev;
  25. int recordIndex; // record # in tunnel build message
  26. TunnelHopConfig (std::shared_ptr<const i2p::data::IdentityEx> r)
  27. {
  28. RAND_bytes (layerKey, 32);
  29. RAND_bytes (ivKey, 32);
  30. RAND_bytes (replyKey, 32);
  31. RAND_bytes (replyIV, 16);
  32. RAND_bytes ((uint8_t *)&tunnelID, 4);
  33. if (!tunnelID) tunnelID = 1; // tunnelID can't be zero
  34. isGateway = true;
  35. isEndpoint = true;
  36. ident = r;
  37. //nextRouter = nullptr;
  38. nextTunnelID = 0;
  39. next = nullptr;
  40. prev = nullptr;
  41. }
  42. void SetNextIdent (const i2p::data::IdentHash& ident)
  43. {
  44. nextIdent = ident;
  45. isEndpoint = false;
  46. RAND_bytes ((uint8_t *)&nextTunnelID, 4);
  47. if (!nextTunnelID) nextTunnelID = 1; // tunnelID can't be zero
  48. }
  49. void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent)
  50. {
  51. nextIdent = replyIdent;
  52. nextTunnelID = replyTunnelID;
  53. isEndpoint = true;
  54. }
  55. void SetNext (TunnelHopConfig * n)
  56. {
  57. next = n;
  58. if (next)
  59. {
  60. next->prev = this;
  61. next->isGateway = false;
  62. isEndpoint = false;
  63. nextIdent = next->ident->GetIdentHash ();
  64. nextTunnelID = next->tunnelID;
  65. }
  66. }
  67. void SetPrev (TunnelHopConfig * p)
  68. {
  69. prev = p;
  70. if (prev)
  71. {
  72. prev->next = this;
  73. prev->isEndpoint = false;
  74. isGateway = false;
  75. }
  76. }
  77. void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) const
  78. {
  79. uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
  80. htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID);
  81. memcpy (clearText + BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET, ident->GetIdentHash (), 32);
  82. htobe32buf (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID);
  83. memcpy (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32);
  84. memcpy (clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, layerKey, 32);
  85. memcpy (clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, ivKey, 32);
  86. memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET, replyKey, 32);
  87. memcpy (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, replyIV, 16);
  88. uint8_t flag = 0;
  89. if (isGateway) flag |= 0x80;
  90. if (isEndpoint) flag |= 0x40;
  91. clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag;
  92. htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ());
  93. htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID);
  94. RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET);
  95. auto encryptor = ident->CreateEncryptor (nullptr);
  96. if (encryptor)
  97. encryptor->Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx, false);
  98. memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
  99. }
  100. };
  101. class TunnelConfig
  102. {
  103. public:
  104. TunnelConfig (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers) // inbound
  105. {
  106. CreatePeers (peers);
  107. m_LastHop->SetNextIdent (i2p::context.GetIdentHash ());
  108. }
  109. TunnelConfig (std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers,
  110. uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) // outbound
  111. {
  112. CreatePeers (peers);
  113. m_FirstHop->isGateway = false;
  114. m_LastHop->SetReplyHop (replyTunnelID, replyIdent);
  115. }
  116. ~TunnelConfig ()
  117. {
  118. TunnelHopConfig * hop = m_FirstHop;
  119. while (hop)
  120. {
  121. auto tmp = hop;
  122. hop = hop->next;
  123. delete tmp;
  124. }
  125. }
  126. TunnelHopConfig * GetFirstHop () const
  127. {
  128. return m_FirstHop;
  129. }
  130. TunnelHopConfig * GetLastHop () const
  131. {
  132. return m_LastHop;
  133. }
  134. int GetNumHops () const
  135. {
  136. int num = 0;
  137. TunnelHopConfig * hop = m_FirstHop;
  138. while (hop)
  139. {
  140. num++;
  141. hop = hop->next;
  142. }
  143. return num;
  144. }
  145. bool IsEmpty () const
  146. {
  147. return !m_FirstHop;
  148. }
  149. virtual bool IsInbound () const { return m_FirstHop->isGateway; }
  150. virtual uint32_t GetTunnelID () const
  151. {
  152. if (!m_FirstHop) return 0;
  153. return IsInbound () ? m_LastHop->nextTunnelID : m_FirstHop->tunnelID;
  154. }
  155. virtual uint32_t GetNextTunnelID () const
  156. {
  157. if (!m_FirstHop) return 0;
  158. return m_FirstHop->tunnelID;
  159. }
  160. virtual const i2p::data::IdentHash& GetNextIdentHash () const
  161. {
  162. return m_FirstHop->ident->GetIdentHash ();
  163. }
  164. virtual const i2p::data::IdentHash& GetLastIdentHash () const
  165. {
  166. return m_LastHop->ident->GetIdentHash ();
  167. }
  168. std::vector<std::shared_ptr<const i2p::data::IdentityEx> > GetPeers () const
  169. {
  170. std::vector<std::shared_ptr<const i2p::data::IdentityEx> > peers;
  171. TunnelHopConfig * hop = m_FirstHop;
  172. while (hop)
  173. {
  174. peers.push_back (hop->ident);
  175. hop = hop->next;
  176. }
  177. return peers;
  178. }
  179. protected:
  180. // this constructor can't be called from outside
  181. TunnelConfig (): m_FirstHop (nullptr), m_LastHop (nullptr)
  182. {
  183. }
  184. private:
  185. template<class Peers>
  186. void CreatePeers (const Peers& peers)
  187. {
  188. TunnelHopConfig * prev = nullptr;
  189. for (const auto& it: peers)
  190. {
  191. auto hop = new TunnelHopConfig (it);
  192. if (prev)
  193. prev->SetNext (hop);
  194. else
  195. m_FirstHop = hop;
  196. prev = hop;
  197. }
  198. m_LastHop = prev;
  199. }
  200. private:
  201. TunnelHopConfig * m_FirstHop, * m_LastHop;
  202. };
  203. class ZeroHopsTunnelConfig: public TunnelConfig
  204. {
  205. public:
  206. ZeroHopsTunnelConfig () { RAND_bytes ((uint8_t *)&m_TunnelID, 4);};
  207. bool IsInbound () const { return true; }; // TODO:
  208. uint32_t GetTunnelID () const { return m_TunnelID; };
  209. uint32_t GetNextTunnelID () const { return m_TunnelID; };
  210. const i2p::data::IdentHash& GetNextIdentHash () const { return i2p::context.GetIdentHash (); };
  211. const i2p::data::IdentHash& GetLastIdentHash () const { return i2p::context.GetIdentHash (); };
  212. private:
  213. uint32_t m_TunnelID;
  214. };
  215. }
  216. }
  217. #endif