1 /*
2 * Copyright (c) 2013-2021, The PurpleI2P Project
3 *
4 * This file is part of Purple i2pd project and licensed under BSD3
5 *
6 * See full license text in LICENSE file at top of project tree
7 */
8 
9 #include <string.h>
10 #include <atomic>
11 #include "Base.h"
12 #include "Log.h"
13 #include "Crypto.h"
14 #include "I2PEndian.h"
15 #include "Timestamp.h"
16 #include "RouterContext.h"
17 #include "NetDb.hpp"
18 #include "Tunnel.h"
19 #include "Transports.h"
20 #include "Garlic.h"
21 #include "ECIESX25519AEADRatchetSession.h"
22 #include "I2NPProtocol.h"
23 #include "version.h"
24 
25 using namespace i2p::transport;
26 
27 namespace i2p
28 {
NewI2NPMessage()29 	std::shared_ptr<I2NPMessage> NewI2NPMessage ()
30 	{
31 		return std::make_shared<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> >();
32 	}
33 
NewI2NPShortMessage()34 	std::shared_ptr<I2NPMessage> NewI2NPShortMessage ()
35 	{
36 		return std::make_shared<I2NPMessageBuffer<I2NP_MAX_SHORT_MESSAGE_SIZE> >();
37 	}
38 
NewI2NPTunnelMessage(bool endpoint)39 	std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
40 	{
41 		return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
42 	}
43 
NewI2NPMessage(size_t len)44 	std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
45 	{
46 		return (len < I2NP_MAX_SHORT_MESSAGE_SIZE - I2NP_HEADER_SIZE - 2) ? NewI2NPShortMessage () : NewI2NPMessage ();
47 	}
48 
FillI2NPMessageHeader(I2NPMessageType msgType,uint32_t replyMsgID,bool checksum)49 	void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum)
50 	{
51 		SetTypeID (msgType);
52 		if (!replyMsgID) RAND_bytes ((uint8_t *)&replyMsgID, 4);
53 		SetMsgID (replyMsgID);
54 		SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT);
55 		UpdateSize ();
56 		if (checksum) UpdateChks ();
57 	}
58 
RenewI2NPMessageHeader()59 	void I2NPMessage::RenewI2NPMessageHeader ()
60 	{
61 		uint32_t msgID;
62 		RAND_bytes ((uint8_t *)&msgID, 4);
63 		SetMsgID (msgID);
64 		SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT);
65 	}
66 
IsExpired() const67 	bool I2NPMessage::IsExpired () const
68 	{
69 		auto ts = i2p::util::GetMillisecondsSinceEpoch ();
70 		auto exp = GetExpiration ();
71 		return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future
72 	}
73 
CreateI2NPMessage(I2NPMessageType msgType,const uint8_t * buf,size_t len,uint32_t replyMsgID)74 	std::shared_ptr<I2NPMessage> CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID)
75 	{
76 		auto msg = NewI2NPMessage (len);
77 		if (msg->Concat (buf, len) < len)
78 			LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length ", msg->maxLen);
79 		msg->FillI2NPMessageHeader (msgType, replyMsgID);
80 		return msg;
81 	}
82 
CreateI2NPMessage(const uint8_t * buf,size_t len,std::shared_ptr<i2p::tunnel::InboundTunnel> from)83 	std::shared_ptr<I2NPMessage> CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
84 	{
85 		auto msg = NewI2NPMessage ();
86 		if (msg->offset + len < msg->maxLen)
87 		{
88 			memcpy (msg->GetBuffer (), buf, len);
89 			msg->len = msg->offset + len;
90 			msg->from = from;
91 		}
92 		else
93 			LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length");
94 		return msg;
95 	}
96 
CopyI2NPMessage(std::shared_ptr<I2NPMessage> msg)97 	std::shared_ptr<I2NPMessage> CopyI2NPMessage (std::shared_ptr<I2NPMessage> msg)
98 	{
99 		if (!msg) return nullptr;
100 		auto newMsg = NewI2NPMessage (msg->len);
101 		newMsg->offset = msg->offset;
102 		*newMsg = *msg;
103 		return newMsg;
104 	}
105 
CreateDeliveryStatusMsg(uint32_t msgID)106 	std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
107 	{
108 		auto m = NewI2NPShortMessage ();
109 		uint8_t * buf = m->GetPayload ();
110 		if (msgID)
111 		{
112 			htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
113 			htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::util::GetMillisecondsSinceEpoch ());
114 		}
115 		else // for SSU establishment
116 		{
117 			RAND_bytes ((uint8_t *)&msgID, 4);
118 			htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
119 			htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::context.GetNetID ());
120 		}
121 		m->len += DELIVERY_STATUS_SIZE;
122 		m->FillI2NPMessageHeader (eI2NPDeliveryStatus);
123 		return m;
124 	}
125 
CreateRouterInfoDatabaseLookupMsg(const uint8_t * key,const uint8_t * from,uint32_t replyTunnelID,bool exploratory,std::set<i2p::data::IdentHash> * excludedPeers)126 	std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
127 		uint32_t replyTunnelID, bool exploratory, std::set<i2p::data::IdentHash> * excludedPeers)
128 	{
129 		auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage ();
130 		uint8_t * buf = m->GetPayload ();
131 		memcpy (buf, key, 32); // key
132 		buf += 32;
133 		memcpy (buf, from, 32); // from
134 		buf += 32;
135 		uint8_t flag = exploratory ? DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP : DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP;
136 		if (replyTunnelID)
137 		{
138 			*buf = flag | DATABASE_LOOKUP_DELIVERY_FLAG; // set delivery flag
139 			htobe32buf (buf+1, replyTunnelID);
140 			buf += 5;
141 		}
142 		else
143 		{
144 			*buf = flag; // flag
145 			buf++;
146 		}
147 
148 		if (excludedPeers)
149 		{
150 			int cnt = excludedPeers->size ();
151 			htobe16buf (buf, cnt);
152 			buf += 2;
153 			for (auto& it: *excludedPeers)
154 			{
155 				memcpy (buf, it, 32);
156 				buf += 32;
157 			}
158 		}
159 		else
160 		{
161 			// nothing to exclude
162 			htobuf16 (buf, 0);
163 			buf += 2;
164 		}
165 
166 		m->len += (buf - m->GetPayload ());
167 		m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
168 		return m;
169 	}
170 
CreateLeaseSetDatabaseLookupMsg(const i2p::data::IdentHash & dest,const std::set<i2p::data::IdentHash> & excludedFloodfills,std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,const uint8_t * replyKey,const uint8_t * replyTag,bool replyECIES)171 	std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
172 		const std::set<i2p::data::IdentHash>& excludedFloodfills,
173 		std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
174 		    const uint8_t * replyTag, bool replyECIES)
175 	{
176 		int cnt = excludedFloodfills.size ();
177 		auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
178 		uint8_t * buf = m->GetPayload ();
179 		memcpy (buf, dest, 32); // key
180 		buf += 32;
181 		memcpy (buf, replyTunnel->GetNextIdentHash (), 32); // reply tunnel GW
182 		buf += 32;
183 		*buf = DATABASE_LOOKUP_DELIVERY_FLAG | DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP; // flags
184 		*buf |= (replyECIES ? DATABASE_LOOKUP_ECIES_FLAG : DATABASE_LOOKUP_ENCRYPTION_FLAG);
185 		buf ++;
186 		htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID
187 		buf += 4;
188 
189 		// excluded
190 		if (cnt > 512)
191 		{
192 			LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup");
193 			cnt = 0;
194 		}
195 		htobe16buf (buf, cnt);
196 		buf += 2;
197 		if (cnt > 0)
198 		{
199 			for (auto& it: excludedFloodfills)
200 			{
201 				memcpy (buf, it, 32);
202 				buf += 32;
203 			}
204 		}
205 		// encryption
206 		memcpy (buf, replyKey, 32);
207 		buf[32] = 1; // 1 tag
208 		if (replyECIES)
209 		{
210 			memcpy (buf + 33, replyTag, 8); // 8 bytes tag
211 			buf += 41;
212 		}
213 		else
214 		{
215 			memcpy (buf + 33, replyTag, 32); // 32 bytes tag
216 			buf += 65;
217 		}
218 
219 		m->len += (buf - m->GetPayload ());
220 		m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
221 		return m;
222 	}
223 
CreateDatabaseSearchReply(const i2p::data::IdentHash & ident,std::vector<i2p::data::IdentHash> routers)224 	std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident,
225 		std::vector<i2p::data::IdentHash> routers)
226 	{
227 		auto m = NewI2NPShortMessage ();
228 		uint8_t * buf = m->GetPayload ();
229 		size_t len = 0;
230 		memcpy (buf, ident, 32);
231 		len += 32;
232 		buf[len] = routers.size ();
233 		len++;
234 		for (const auto& it: routers)
235 		{
236 			memcpy (buf + len, it, 32);
237 			len += 32;
238 		}
239 		memcpy (buf + len, i2p::context.GetRouterInfo ().GetIdentHash (), 32);
240 		len += 32;
241 		m->len += len;
242 		m->FillI2NPMessageHeader (eI2NPDatabaseSearchReply);
243 		return m;
244 	}
245 
CreateDatabaseStoreMsg(std::shared_ptr<const i2p::data::RouterInfo> router,uint32_t replyToken,std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)246 	std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
247 	    uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
248 	{
249 		if (!router) // we send own RouterInfo
250 			router = context.GetSharedRouterInfo ();
251 
252 		if (!router->GetBuffer ())
253 		{
254 			LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore");
255 			return nullptr;
256 		}
257 
258 		auto m = NewI2NPShortMessage ();
259 		uint8_t * payload = m->GetPayload ();
260 
261 		memcpy (payload + DATABASE_STORE_KEY_OFFSET, router->GetIdentHash (), 32);
262 		payload[DATABASE_STORE_TYPE_OFFSET] = 0; // RouterInfo
263 		htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken);
264 		uint8_t * buf = payload + DATABASE_STORE_HEADER_SIZE;
265 		if (replyToken)
266 		{
267 			if (replyTunnel)
268 			{
269 				htobe32buf (buf, replyTunnel->GetNextTunnelID ());
270 				buf += 4; // reply tunnelID
271 				memcpy (buf, replyTunnel->GetNextIdentHash (), 32);
272 				buf += 32; // reply tunnel gateway
273 			}
274 			else
275 			{
276 				memset (buf, 0, 4); // zero tunnelID means direct reply
277 				buf += 4;
278 				memcpy (buf, context.GetIdentHash (), 32);
279 				buf += 32;
280 			}
281 		}
282 
283 		uint8_t * sizePtr = buf;
284 		buf += 2;
285 		m->len += (buf - payload); // payload size
286 		size_t size = 0;
287 		if (router->GetBufferLen () + (buf - payload) <= 940) // fits one tunnel message
288 			size = i2p::data::GzipNoCompression (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len);
289 		else
290 		{
291 			i2p::data::GzipDeflator deflator;
292 			size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len);
293 		}
294 		if (size)
295 		{
296 			htobe16buf (sizePtr, size); // size
297 			m->len += size;
298 		}
299 		else
300 			m = nullptr;
301 		if (m)
302 			m->FillI2NPMessageHeader (eI2NPDatabaseStore);
303 		return m;
304 	}
305 
CreateDatabaseStoreMsg(const i2p::data::IdentHash & storeHash,std::shared_ptr<const i2p::data::LeaseSet> leaseSet)306 	std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (const i2p::data::IdentHash& storeHash, std::shared_ptr<const i2p::data::LeaseSet> leaseSet)
307 	{
308 		if (!leaseSet) return nullptr;
309 		auto m = NewI2NPShortMessage ();
310 		uint8_t * payload = m->GetPayload ();
311 		memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32);
312 		payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet
313 		htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
314 		size_t size = DATABASE_STORE_HEADER_SIZE;
315 		memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
316 		size += leaseSet->GetBufferLen ();
317 		m->len += size;
318 		m->FillI2NPMessageHeader (eI2NPDatabaseStore);
319 		return m;
320 	}
321 
CreateDatabaseStoreMsg(std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet,uint32_t replyToken,std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)322 	std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
323 	{
324 		if (!leaseSet) return nullptr;
325 		auto m = NewI2NPShortMessage ();
326 		uint8_t * payload = m->GetPayload ();
327 		memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetStoreHash (), 32);
328 		payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // LeaseSet or LeaseSet2
329 		htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken);
330 		size_t size = DATABASE_STORE_HEADER_SIZE;
331 		if (replyToken && replyTunnel)
332 		{
333 			if (replyTunnel)
334 			{
335 				htobe32buf (payload + size, replyTunnel->GetNextTunnelID ());
336 				size += 4; // reply tunnelID
337 				memcpy (payload + size, replyTunnel->GetNextIdentHash (), 32);
338 				size += 32; // reply tunnel gateway
339 			}
340 			else
341 				htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
342 		}
343 		memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
344 		size += leaseSet->GetBufferLen ();
345 		m->len += size;
346 		m->FillI2NPMessageHeader (eI2NPDatabaseStore);
347 		return m;
348 	}
349 
IsRouterInfoMsg(std::shared_ptr<I2NPMessage> msg)350 	bool IsRouterInfoMsg (std::shared_ptr<I2NPMessage> msg)
351 	{
352 		if (!msg || msg->GetTypeID () != eI2NPDatabaseStore) return false;
353 		return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo
354 	}
355 
356 	static uint16_t g_MaxNumTransitTunnels = DEFAULT_MAX_NUM_TRANSIT_TUNNELS; // TODO:
SetMaxNumTransitTunnels(uint16_t maxNumTransitTunnels)357 	void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels)
358 	{
359 		if (maxNumTransitTunnels > 0 && g_MaxNumTransitTunnels != maxNumTransitTunnels)
360 		{
361 			LogPrint (eLogDebug, "I2NP: Max number of transit tunnels set to ", maxNumTransitTunnels);
362 			g_MaxNumTransitTunnels = maxNumTransitTunnels;
363 		}
364 	}
365 
GetMaxNumTransitTunnels()366 	uint16_t GetMaxNumTransitTunnels ()
367 	{
368 		return g_MaxNumTransitTunnels;
369 	}
370 
HandleBuildRequestRecords(int num,uint8_t * records,uint8_t * clearText)371 	static bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText)
372 	{
373 		for (int i = 0; i < num; i++)
374 		{
375 			uint8_t * record = records + i*TUNNEL_BUILD_RECORD_SIZE;
376 			if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16))
377 			{
378 				LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
379 				if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
380 				uint8_t retCode = 0;
381 				// replace record to reply
382 				if (i2p::context.AcceptsTunnels () &&
383 					i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels &&
384 					!i2p::transport::transports.IsBandwidthExceeded () &&
385 					!i2p::transport::transports.IsTransitBandwidthExceeded ())
386 				{
387 					auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
388 							bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
389 							clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
390 							bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
391 							clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
392 							clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
393 							clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
394 							clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
395 					i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
396 				}
397 				else
398 					retCode = 30; // always reject with bandwidth reason (30)
399 
400 				memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
401 				record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
402 				// encrypt reply
403 				i2p::crypto::CBCEncryption encryption;
404 				for (int j = 0; j < num; j++)
405 				{
406 					uint8_t * reply = records + j*TUNNEL_BUILD_RECORD_SIZE;
407 					if (j == i)
408 					{
409 						uint8_t nonce[12];
410 						memset (nonce, 0, 12);
411 						auto& noiseState = i2p::context.GetCurrentNoiseState ();
412 						if (!i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16,
413 							noiseState.m_H, 32, noiseState.m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
414 						{
415 							LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed");
416 							return false;
417 						}
418 					}
419 					else
420 					{
421 						encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET);
422 						encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET);
423 						encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply);
424 					}
425 				}
426 				return true;
427 			}
428 		}
429 		return false;
430 	}
431 
HandleVariableTunnelBuildMsg(uint32_t replyMsgID,uint8_t * buf,size_t len)432 	static void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
433 	{
434 		int num = buf[0];
435 		LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records");
436 		if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1)
437 		{
438 			LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len);
439 			return;
440 		}
441 
442 		auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
443 		if (tunnel)
444 		{
445 			// endpoint of inbound tunnel
446 			LogPrint (eLogDebug, "I2NP: VariableTunnelBuild reply for tunnel ", tunnel->GetTunnelID ());
447 			if (tunnel->HandleTunnelBuildResponse (buf, len))
448 			{
449 				LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been created");
450 				tunnel->SetState (i2p::tunnel::eTunnelStateEstablished);
451 				i2p::tunnel::tunnels.AddInboundTunnel (tunnel);
452 			}
453 			else
454 			{
455 				LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been declined");
456 				tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);
457 			}
458 		}
459 		else
460 		{
461 			uint8_t clearText[ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
462 			if (HandleBuildRequestRecords (num, buf + 1, clearText))
463 			{
464 				if (clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG) // we are endpoint of outboud tunnel
465 				{
466 					// so we send it to reply tunnel
467 					transports.SendMessage (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
468 						CreateTunnelGatewayMsg (bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
469 							eI2NPVariableTunnelBuildReply, buf, len,
470 							bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
471 				}
472 				else
473 					transports.SendMessage (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
474 						CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len,
475 							bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
476 			}
477 		}
478 	}
479 
HandleTunnelBuildMsg(uint8_t * buf,size_t len)480 	static void HandleTunnelBuildMsg (uint8_t * buf, size_t len)
481 	{
482 		LogPrint (eLogWarning, "I2NP: TunnelBuild is too old for ECIES router");
483 	}
484 
HandleTunnelBuildReplyMsg(uint32_t replyMsgID,uint8_t * buf,size_t len,bool isShort)485 	static void HandleTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len, bool isShort)
486 	{
487 		int num = buf[0];
488 		LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID);
489 		size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
490 		if (len < num*recordSize + 1)
491 		{
492 			LogPrint (eLogError, "I2NP: TunnelBuildReply message of ", num, " records is too short ", len);
493 			return;
494 		}
495 
496 		auto tunnel = i2p::tunnel::tunnels.GetPendingOutboundTunnel (replyMsgID);
497 		if (tunnel)
498 		{
499 			// reply for outbound tunnel
500 			if (tunnel->HandleTunnelBuildResponse (buf, len))
501 			{
502 				LogPrint (eLogInfo, "I2NP: Outbound tunnel ", tunnel->GetTunnelID (), " has been created");
503 				tunnel->SetState (i2p::tunnel::eTunnelStateEstablished);
504 				i2p::tunnel::tunnels.AddOutboundTunnel (tunnel);
505 			}
506 			else
507 			{
508 				LogPrint (eLogInfo, "I2NP: Outbound tunnel ", tunnel->GetTunnelID (), " has been declined");
509 				tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);
510 			}
511 		}
512 		else
513 			LogPrint (eLogWarning, "I2NP: Pending tunnel for message ", replyMsgID, " not found");
514 	}
515 
HandleShortTunnelBuildMsg(uint32_t replyMsgID,uint8_t * buf,size_t len)516 	static void HandleShortTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
517 	{
518 		int num = buf[0];
519 		LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records");
520 		if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1)
521 		{
522 			LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len);
523 			return;
524 		}
525 		auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
526 		if (tunnel)
527 		{
528 			// endpoint of inbound tunnel
529 			LogPrint (eLogDebug, "I2NP: ShortTunnelBuild reply for tunnel ", tunnel->GetTunnelID ());
530 			if (tunnel->HandleTunnelBuildResponse (buf, len))
531 			{
532 				LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been created");
533 				tunnel->SetState (i2p::tunnel::eTunnelStateEstablished);
534 				i2p::tunnel::tunnels.AddInboundTunnel (tunnel);
535 			}
536 			else
537 			{
538 				LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been declined");
539 				tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);
540 			}
541 			return;
542 		}
543 		const uint8_t * record = buf + 1;
544 		for (int i = 0; i < num; i++)
545 		{
546 			if (!memcmp (record, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16))
547 			{
548 				LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours");
549 				uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE];
550 				if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
551 				{
552 					LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i);
553 					return;
554 				}
555 				if (clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE]) // not AES
556 				{
557 					LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record");
558 					return;
559 				}
560 				auto& noiseState = i2p::context.GetCurrentNoiseState ();
561 				uint8_t replyKey[32], layerKey[32], ivKey[32];
562 				i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
563 				memcpy (replyKey, noiseState.m_CK + 32, 32);
564 				i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK);
565 				memcpy (layerKey, noiseState.m_CK + 32, 32);
566 				bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
567 				if (isEndpoint)
568 				{
569 					i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "TunnelLayerIVKey", noiseState.m_CK);
570 					memcpy (ivKey, noiseState.m_CK + 32, 32);
571 				}
572 				else
573 					memcpy (ivKey, noiseState.m_CK , 32);
574 
575 				// check if we accept this tunnel
576 				uint8_t retCode = 0;
577 				if (!i2p::context.AcceptsTunnels () ||
578 					i2p::tunnel::tunnels.GetTransitTunnels ().size () > g_MaxNumTransitTunnels ||
579 					i2p::transport::transports.IsBandwidthExceeded () ||
580 					i2p::transport::transports.IsTransitBandwidthExceeded ())
581 						retCode = 30;
582 				if (!retCode)
583 				{
584 					// create new transit tunnel
585 					auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
586 						bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
587 						clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
588 						bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
589 						layerKey, ivKey,
590 						clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
591 						clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
592 					i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
593 				}
594 
595 				// encrypt reply
596 				uint8_t nonce[12];
597 				memset (nonce, 0, 12);
598 				uint8_t * reply = buf + 1;
599 				for (int j = 0; j < num; j++)
600 				{
601 					nonce[4] = j; // nonce is record #
602 					if (j == i)
603 					{
604 						memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
605 						reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = retCode;
606 						if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16,
607 							noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
608 						{
609 							LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed");
610 							return;
611 						}
612 					}
613 					else
614 						i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply);
615 					reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
616 				}
617 				// send reply
618 				if (isEndpoint)
619 				{
620 					auto replyMsg = NewI2NPShortMessage ();
621 					replyMsg->Concat (buf, len);
622 					replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
623 					if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (),
624 						clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local?
625 					{
626 						i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK);
627 						uint64_t tag;
628 						memcpy (&tag, noiseState.m_CK, 8);
629 						// we send it to reply tunnel
630 						transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
631 						CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
632 							i2p::garlic::WrapECIESX25519Message (replyMsg,  noiseState.m_CK + 32, tag)));
633 					}
634 					else
635 					{
636 						// IBGW is local
637 						uint32_t tunnelID = bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET);
638 						auto tunnel = i2p::tunnel::tunnels.GetTunnel (tunnelID);
639 						if (tunnel)
640 							tunnel->SendTunnelDataMsg (replyMsg);
641 						else
642 							LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
643 					}
644 				}
645 				else
646 					transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
647 						CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
648 							bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
649 				return;
650 			}
651 			record += SHORT_TUNNEL_BUILD_RECORD_SIZE;
652 		}
653 	}
654 
CreateTunnelDataMsg(const uint8_t * buf)655 	std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf)
656 	{
657 		auto msg = NewI2NPTunnelMessage (false);
658 		msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE);
659 		msg->FillI2NPMessageHeader (eI2NPTunnelData);
660 		return msg;
661 	}
662 
CreateTunnelDataMsg(uint32_t tunnelID,const uint8_t * payload)663 	std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload)
664 	{
665 		auto msg = NewI2NPTunnelMessage (false);
666 		htobe32buf (msg->GetPayload (), tunnelID);
667 		msg->len += 4; // tunnelID
668 		msg->Concat (payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4);
669 		msg->FillI2NPMessageHeader (eI2NPTunnelData);
670 		return msg;
671 	}
672 
CreateEmptyTunnelDataMsg(bool endpoint)673 	std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg (bool endpoint)
674 	{
675 		auto msg = NewI2NPTunnelMessage (endpoint);
676 		msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE;
677 		return msg;
678 	}
679 
CreateTunnelGatewayMsg(uint32_t tunnelID,const uint8_t * buf,size_t len)680 	std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len)
681 	{
682 		auto msg = NewI2NPMessage (len);
683 		uint8_t * payload = msg->GetPayload ();
684 		htobe32buf (payload + TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET, tunnelID);
685 		htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
686 		msg->len += TUNNEL_GATEWAY_HEADER_SIZE;
687 		if (msg->Concat (buf, len) < len)
688 			LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
689 		msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
690 		return msg;
691 	}
692 
CreateTunnelGatewayMsg(uint32_t tunnelID,std::shared_ptr<I2NPMessage> msg)693 	std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr<I2NPMessage> msg)
694 	{
695 		if (msg->offset >= I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE)
696 		{
697 			// message is capable to be used without copying
698 			uint8_t * payload = msg->GetBuffer () - TUNNEL_GATEWAY_HEADER_SIZE;
699 			htobe32buf (payload + TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET, tunnelID);
700 			int len = msg->GetLength ();
701 			htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
702 			msg->offset -= (I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE);
703 			msg->len = msg->offset + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE +len;
704 			msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
705 			return msg;
706 		}
707 		else
708 			return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ());
709 	}
710 
CreateTunnelGatewayMsg(uint32_t tunnelID,I2NPMessageType msgType,const uint8_t * buf,size_t len,uint32_t replyMsgID)711 	std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType,
712 		const uint8_t * buf, size_t len, uint32_t replyMsgID)
713 	{
714 		auto msg = NewI2NPMessage (len);
715 		size_t gatewayMsgOffset = I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE;
716 		msg->offset += gatewayMsgOffset;
717 		msg->len += gatewayMsgOffset;
718 		if (msg->Concat (buf, len) < len)
719 			LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
720 		msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message
721 		len = msg->GetLength ();
722 		msg->offset -= gatewayMsgOffset;
723 		uint8_t * payload = msg->GetPayload ();
724 		htobe32buf (payload + TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET, tunnelID);
725 		htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
726 		msg->FillI2NPMessageHeader (eI2NPTunnelGateway); // gateway message
727 		return msg;
728 	}
729 
GetI2NPMessageLength(const uint8_t * msg,size_t len)730 	size_t GetI2NPMessageLength (const uint8_t * msg, size_t len)
731 	{
732 		if (len < I2NP_HEADER_SIZE_OFFSET + 2)
733 		{
734 			LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
735 			return len;
736 		}
737 		auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
738 		if (l > len)
739 		{
740 			LogPrint (eLogError, "I2NP: Message length ", l, " exceeds buffer length ", len);
741 			l = len;
742 		}
743 		return l;
744 	}
745 
HandleI2NPMessage(uint8_t * msg,size_t len)746 	void HandleI2NPMessage (uint8_t * msg, size_t len)
747 	{
748 		if (len < I2NP_HEADER_SIZE)
749 		{
750 			LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
751 			return;
752 		}
753 		uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
754 		uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
755 		LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
756 		uint8_t * buf = msg + I2NP_HEADER_SIZE;
757 		auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
758 		len -= I2NP_HEADER_SIZE;
759 		if (size > len)
760 		{
761 			LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
762 			size = len;
763 		}
764 		switch (typeID)
765 		{
766 			case eI2NPVariableTunnelBuild:
767 				HandleVariableTunnelBuildMsg (msgID, buf, size);
768 			break;
769 			case eI2NPShortTunnelBuild:
770 				HandleShortTunnelBuildMsg (msgID, buf, size);
771 			break;
772 			case eI2NPVariableTunnelBuildReply:
773 				HandleTunnelBuildReplyMsg (msgID, buf, size, false);
774 			break;
775 			case eI2NPShortTunnelBuildReply:
776 				HandleTunnelBuildReplyMsg (msgID, buf, size, true);
777 			break;
778 			case eI2NPTunnelBuild:
779 				HandleTunnelBuildMsg (buf, size);
780 			break;
781 			case eI2NPTunnelBuildReply:
782 				// TODO:
783 			break;
784 			default:
785 				LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID);
786 		}
787 	}
788 
HandleI2NPMessage(std::shared_ptr<I2NPMessage> msg)789 	void HandleI2NPMessage (std::shared_ptr<I2NPMessage> msg)
790 	{
791 		if (msg)
792 		{
793 			uint8_t typeID = msg->GetTypeID ();
794 			LogPrint (eLogDebug, "I2NP: Handling message with type ", (int)typeID);
795 			switch (typeID)
796 			{
797 				case eI2NPTunnelData:
798 					i2p::tunnel::tunnels.PostTunnelData (msg);
799 				break;
800 				case eI2NPTunnelGateway:
801 					i2p::tunnel::tunnels.PostTunnelData (msg);
802 				break;
803 				case eI2NPGarlic:
804 				{
805 					if (msg->from)
806 					{
807 						if (msg->from->GetTunnelPool ())
808 							msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
809 						else
810 							LogPrint (eLogInfo, "I2NP: Local destination for garlic doesn't exist anymore");
811 					}
812 					else
813 						i2p::context.ProcessGarlicMessage (msg);
814 					break;
815 				}
816 				case eI2NPDatabaseStore:
817 				case eI2NPDatabaseSearchReply:
818 				case eI2NPDatabaseLookup:
819 					// forward to netDb
820 					i2p::data::netdb.PostI2NPMsg (msg);
821 				break;
822 				case eI2NPDeliveryStatus:
823 				{
824 					if (msg->from && msg->from->GetTunnelPool ())
825 						msg->from->GetTunnelPool ()->ProcessDeliveryStatus (msg);
826 					else
827 						i2p::context.ProcessDeliveryStatusMessage (msg);
828 					break;
829 				}
830 				case eI2NPVariableTunnelBuild:
831 				case eI2NPVariableTunnelBuildReply:
832 				case eI2NPTunnelBuild:
833 				case eI2NPTunnelBuildReply:
834 				case eI2NPShortTunnelBuild:
835 				case eI2NPShortTunnelBuildReply:
836 					// forward to tunnel thread
837 					i2p::tunnel::tunnels.PostTunnelData (msg);
838 				break;
839 				default:
840 					HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
841 			}
842 		}
843 	}
844 
~I2NPMessagesHandler()845 	I2NPMessagesHandler::~I2NPMessagesHandler ()
846 	{
847 		Flush ();
848 	}
849 
PutNextMessage(std::shared_ptr<I2NPMessage> && msg)850 	void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage>&& msg)
851 	{
852 		if (msg)
853 		{
854 			switch (msg->GetTypeID ())
855 			{
856 				case eI2NPTunnelData:
857 					m_TunnelMsgs.push_back (msg);
858 				break;
859 				case eI2NPTunnelGateway:
860 					m_TunnelGatewayMsgs.push_back (msg);
861 				break;
862 				default:
863 					HandleI2NPMessage (msg);
864 			}
865 		}
866 	}
867 
Flush()868 	void I2NPMessagesHandler::Flush ()
869 	{
870 		if (!m_TunnelMsgs.empty ())
871 		{
872 			i2p::tunnel::tunnels.PostTunnelData (m_TunnelMsgs);
873 			m_TunnelMsgs.clear ();
874 		}
875 		if (!m_TunnelGatewayMsgs.empty ())
876 		{
877 			i2p::tunnel::tunnels.PostTunnelData (m_TunnelGatewayMsgs);
878 			m_TunnelGatewayMsgs.clear ();
879 		}
880 	}
881 }
882