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