MCPcopy Create free account
hub / github.com/PurpleI2P/i2pd / HandleGarlicMessage

Method HandleGarlicMessage

libi2pd/Garlic.cpp:498–568  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

496 }
497
498 void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
499 {
500 uint8_t * buf = msg->GetPayload ();
501 uint32_t length = bufbe32toh (buf);
502 if (length > msg->GetLength ())
503 {
504 LogPrint (eLogWarning, "Garlic: Message length ", length, " exceeds I2NP message length ", msg->GetLength ());
505 return;
506 }
507 auto mod = length & 0x0f; // %16
508 buf += 4; // length
509
510 bool found = false;
511 bool supportsRatchets = SupportsRatchets ();
512 if (supportsRatchets)
513 // try ECIESx25519 tag
514 found = HandleECIESx25519TagMessage (buf, length);
515 if (!found)
516 {
517 auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
518 // AES tag might be used even if encryption type is not ElGamal/AES
519 if (it != m_Tags.end ()) // try AES tag
520 {
521 // tag found. Use AES
522 auto decryption = it->second;
523 m_Tags.erase (it); // tag might be used only once
524 if (length >= 32)
525 {
526 uint8_t iv[32]; // IV is first 16 bytes
527 SHA256(buf, 32, iv);
528 decryption->Decrypt (buf + 32, length - 32, iv, buf + 32);
529 HandleAESBlock (buf + 32, length - 32, decryption, msg->from);
530 found = true;
531 }
532 else
533 LogPrint (eLogWarning, "Garlic: Message length ", length, " is less than 32 bytes");
534 }
535 if (!found) // assume new session
536 {
537 // AES tag not found. Handle depending on encryption type
538 // try ElGamal/AES first if leading block is 514
539 ElGamalBlock elGamal;
540 if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) &&
541 Decrypt (buf, (uint8_t *)&elGamal, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
542 {
543 auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
544 uint8_t iv[32]; // IV is first 16 bytes
545 SHA256(elGamal.preIV, 32, iv);
546 decryption->Decrypt(buf + 514, length - 514, iv, buf + 514);
547 HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
548 }
549 else if (supportsRatchets)
550 {
551 // otherwise ECIESx25519
552 auto ts = i2p::util::GetMillisecondsSinceEpoch ();
553 if (ts > m_LastIncomingSessionTimestamp + INCOMING_SESSIONS_MINIMAL_INTERVAL)
554 {
555 auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming

Callers 1

ProcessGarlicMessageMethod · 0.80

Calls 8

bufbe32tohFunction · 0.85
LogPrintFunction · 0.85
SessionTagClass · 0.85
GetPayloadMethod · 0.45
GetLengthMethod · 0.45
DecryptMethod · 0.45
HandleNextMessageMethod · 0.45

Tested by

no test coverage detected