Example #1
0
	size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg, bool isDestination)
	{
		uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
		size_t size = 0;
		if (isDestination)
		{
			buf[size] = eGarlicDeliveryTypeDestination << 5;//  delivery instructions flag destination
			size++;
			memcpy (buf + size, m_Destination->GetIdentHash (), 32);
			size += 32;
		}
		else
		{
			buf[size] = 0;//  delivery instructions flag local
			size++;
		}

		memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
		size += msg->GetLength ();
		uint32_t cloveID;
		RAND_bytes ((uint8_t *)&cloveID, 4);
		htobe32buf (buf + size, cloveID); // CloveID
		size += 4;
		htobe64buf (buf + size, ts); // Expiration of clove
		size += 8;
		memset (buf + size, 0, 3); // certificate of clove
		size += 3;
		return size;
	}
Example #2
0
	size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags)
	{
		uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
		uint32_t msgID;
		RAND_bytes ((uint8_t *)&msgID, 4);
		size_t size = 0;
		uint8_t * numCloves = payload + size;
		*numCloves = 0;
		size++;

		if (m_Owner)
		{	
			// resubmit non-confirmed LeaseSet
			if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && 
			    i2p::util::GetMillisecondsSinceEpoch () > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT)
					m_LeaseSetUpdateStatus = eLeaseSetUpdated;

			// attach DeviveryStatus if necessary
			if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated
			{
				// clove is DeliveryStatus 
				auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID);
				if (cloveSize > 0) // successive?
				{
					size += cloveSize;
					(*numCloves)++;
					if (newTags) // new tags created
						m_UnconfirmedTagsMsgs[msgID] = newTags;
					m_Owner->DeliveryStatusSent (shared_from_this (), msgID);
				}
				else
					LogPrint (eLogWarning, "Garlic: DeliveryStatus clove was not created");
			}	
			// attach LeaseSet
			if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) 
			{
				m_LeaseSetUpdateStatus = eLeaseSetSubmitted;
				m_LeaseSetUpdateMsgID = msgID;
				m_LeaseSetSubmissionTime = i2p::util::GetMillisecondsSinceEpoch ();
				// clove if our leaseSet must be attached
				auto leaseSet = CreateDatabaseStoreMsg (m_Owner->GetLeaseSet ());
				size += CreateGarlicClove (payload + size, leaseSet, false); 
				(*numCloves)++;
			}
		}	
		if (msg) // clove message ifself if presented
		{	
			size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false);
			(*numCloves)++;
		}	
		
		memset (payload + size, 0, 3); // certificate of message
		size += 3;
		htobe32buf (payload + size, msgID); // MessageID
		size += 4;
		htobe64buf (payload + size, ts); // Expiration of message
		size += 8;
		return size;
	}	
Example #3
0
	std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
	{
		auto m = NewI2NPShortMessage ();
		uint8_t * buf = m->GetPayload ();
		if (msgID)
		{
			htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
			htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::util::GetMillisecondsSinceEpoch ());
		}
		else // for SSU establishment
		{
			RAND_bytes ((uint8_t *)&msgID, 4);
			htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID);
			htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, 2); // netID = 2
		}	
		m->len += DELIVERY_STATUS_SIZE;
		m->FillI2NPMessageHeader (eI2NPDeliveryStatus);
		return m;
	}
Example #4
0
	size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID)
	{
		size_t size = 0;
		if (m_Owner)
		{
			auto inboundTunnel = m_Owner->GetTunnelPool ()->GetNextInboundTunnel ();
			if (inboundTunnel)
			{
				buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel
				size++;
				// hash and tunnelID sequence is reversed for Garlic
				memcpy (buf + size, inboundTunnel->GetNextIdentHash (), 32); // To Hash
				size += 32;
				htobe32buf (buf + size, inboundTunnel->GetNextTunnelID ()); // tunnelID
				size += 4;
				// create msg
				auto msg = CreateDeliveryStatusMsg (msgID);
				if (m_Owner)
				{
					//encrypt
					uint8_t key[32], tag[32];
					RAND_bytes (key, 32); // random session key
					RAND_bytes (tag, 32); // random session tag
					m_Owner->SubmitSessionKey (key, tag);
					GarlicRoutingSession garlic (key, tag);
					msg = garlic.WrapSingleMessage (msg);
				}
				memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
				size += msg->GetLength ();
				// fill clove
				uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
				uint32_t cloveID;
				RAND_bytes ((uint8_t *)&cloveID, 4);
				htobe32buf (buf + size, cloveID); // CloveID
				size += 4;
				htobe64buf (buf + size, ts); // Expiration of clove
				size += 8;
				memset (buf + size, 0, 3); // certificate of clove
				size += 3;
			}
			else
				LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus");
		}
		else
			LogPrint (eLogWarning, "Garlic: Missing local LeaseSet");

		return size;
	}
Example #5
0
	LeaseSet::LeaseSet (std::shared_ptr<const i2p::tunnel::TunnelPool> pool):
		m_IsValid (true)
	{	
		if (!pool) return;
		// header
		auto localDestination = pool->GetLocalDestination ();
		if (!localDestination)
		{
			m_Buffer = nullptr;
			m_BufferLen = 0;
			m_IsValid = false;
			LogPrint (eLogError, "LeaseSet: Destination for local LeaseSet doesn't exist");
			return;
		}	
		m_Buffer = new uint8_t[MAX_LS_BUFFER_SIZE];
		m_BufferLen = localDestination->GetIdentity ()->ToBuffer (m_Buffer, MAX_LS_BUFFER_SIZE);
		memcpy (m_Buffer + m_BufferLen, localDestination->GetEncryptionPublicKey (), 256);
		m_BufferLen += 256;
		auto signingKeyLen = localDestination->GetIdentity ()->GetSigningPublicKeyLen ();
		memset (m_Buffer + m_BufferLen, 0, signingKeyLen);
		m_BufferLen += signingKeyLen;
		auto tunnels = pool->GetInboundTunnels (5); // 5 tunnels maximum
		m_Buffer[m_BufferLen] = tunnels.size (); // num leases
		m_BufferLen++;
		// leases
		for (auto it: tunnels)
		{	
			memcpy (m_Buffer + m_BufferLen, it->GetNextIdentHash (), 32);
			m_BufferLen += 32; // gateway id
			htobe32buf (m_Buffer + m_BufferLen, it->GetNextTunnelID ());
			m_BufferLen += 4; // tunnel id
			uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration
			ts *= 1000; // in milliseconds
			ts += rand () % 6; // + random milliseconds 0-5
			htobe64buf (m_Buffer + m_BufferLen, ts);
			m_BufferLen += 8; // end date
		}
		// signature
		localDestination->Sign (m_Buffer, m_BufferLen, m_Buffer + m_BufferLen);
		m_BufferLen += localDestination->GetIdentity ()->GetSignatureLen (); 
		LogPrint (eLogDebug, "LeaseSet: Local LeaseSet of ", tunnels.size (), " leases created");

		ReadFromBuffer ();
	}
Example #6
0
	size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags)
	{
		uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
		uint32_t msgID;
		RAND_bytes ((uint8_t *)&msgID, 4);
		size_t size = 0;
		uint8_t * numCloves = payload + size;
		*numCloves = 0;
		size++;

		if (m_Owner)
		{
			// resubmit non-confirmed LeaseSet
			if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && ts > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT)
			{
				m_LeaseSetUpdateStatus = eLeaseSetUpdated;
				SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed
			}

			// attach DeviveryStatus if necessary
			if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated
			{
				// clove is DeliveryStatus
				auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID);
				if (cloveSize > 0) // successive?
				{
					size += cloveSize;
					(*numCloves)++;
					if (newTags) // new tags created
					{
						newTags->msgID = msgID;
						m_UnconfirmedTagsMsgs.insert (std::make_pair(msgID, std::unique_ptr<UnconfirmedTags>(newTags)));
						newTags = nullptr; // got acquired
					}
					m_Owner->DeliveryStatusSent (shared_from_this (), msgID);
				}
				else
					LogPrint (eLogWarning, "Garlic: DeliveryStatus clove was not created");
			}
			// attach LeaseSet
			if (m_LeaseSetUpdateStatus == eLeaseSetUpdated)
			{
				if (m_LeaseSetUpdateMsgID) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); // remove previous
				m_LeaseSetUpdateStatus = eLeaseSetSubmitted;
				m_LeaseSetUpdateMsgID = msgID;
				m_LeaseSetSubmissionTime = ts;
				// clove if our leaseSet must be attached
				auto leaseSet = CreateDatabaseStoreMsg (m_Owner->GetLeaseSet ());
				size += CreateGarlicClove (payload + size, leaseSet, false);
				(*numCloves)++;
			}
		}
		if (msg) // clove message ifself if presented
		{
			size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false);
			(*numCloves)++;
		}
		memset (payload + size, 0, 3); // certificate of message
		size += 3;
		htobe32buf (payload + size, msgID); // MessageID
		size += 4;
		htobe64buf (payload + size, ts + 8000); // Expiration of message, 8 sec
		size += 8;

		if (newTags) delete newTags; // not acquired, delete
		return size;
	}