Example #1
0
void CKadHandler::HandleCryptoResponse(const CVariant& Response, CKadNode* pNode, CComChannel* pChannel)
{
	SKadData* pData = pChannel->GetData<SKadData>();
	if(GetParent<CKademlia>()->Cfg()->GetBool("DebugTL"))
		LogLine(LOG_DEBUG, L"Recived 'CryptoResponse' to %s", pNode->GetID().ToHex().c_str());

	SKeyExchange* Key = NULL;
	TExchangeMap::iterator I = m_KeyExchanges.find(SKadNode(pNode));
	for(; I != m_KeyExchanges.end() && I->first.pNode == pNode; I++)
	{
		if(I->first.pChannel == pChannel)
		{
			Key = &I->second;
			break;
		}
	}
	if(!Key)
		throw CException(LOG_ERROR | LOG_DEBUG, L"Unsolicited Crypto Response");

	CScoped<CSymmetricKey> pCryptoKey;
	try
	{
		if(Response.Has("ERR"))
		{
			string Error = Response["ERR"];
			if(Error == "UnknownKey")
			{
				pNode->SetTrustedKey(NULL);
				Key->pExchange = NULL;
				ResumeExchange(I->first.pNode);
				return;
			}
			else
				throw CException(LOG_ERROR | LOG_DEBUG, L"Crypto Response Returned Error: %S", Error.c_str());
		}

		CScoped<CAbstractKey> pSessionKey;
		if(Key->pExchange->GetAlgorithm() & CAbstractKey::eKeyExchange)
		{
			if(!Response.Has("EK"))
				throw "MissingEK";
			CScoped<CAbstractKey> pRemKey = new CAbstractKey(Response["EK"].GetData(), Response["EK"].GetSize());
			pSessionKey = Key->pExchange->FinaliseKeyExchange(pRemKey);
			if(!pSessionKey)
				throw "ExchangeFailed";

			if(Key->bAuthenticate)
			{
				CPublicKey* pPubKey;
				if(Response.Has("PK")) 
					pPubKey = pNode->SetIDKey(Response);
				else
					pPubKey = pNode->GetID().GetKey();

				if(!pPubKey)
					throw "MissingKey";

				if(!Response.Verify(pPubKey))
					throw "InvalidSign";
			}

			pData->Authenticated = Key->bAuthenticate;
			pNode->SetTrustedKey(new CTrustedKey(pSessionKey->GetKey(), pSessionKey->GetSize(), Key->bAuthenticate));

			ResumeExchange(I->first.pNode);
		}
		else
		{
			pData->Authenticated = Key->bAuthenticate;
			pSessionKey = Key->pExchange->FinaliseKeyExchange(NULL);
		}

		if(Response.Has("IV"))
		{
			UINT eAlgorithm = PrepSC(Key->eAlgorithm); // UINT eAlgorithm = PrepSC(Key->pExchange->GetIV()->GetAlgorithm());

			CAbstractKey InIV(Response["IV"].GetData(), Response["IV"].GetSize());

			pCryptoKey = NewSymmetricKey(eAlgorithm, pSessionKey, &InIV, Key->pExchange->GetIV());
		}
	}
	catch(const char* Error)
	{
		throw CException(LOG_ERROR | LOG_DEBUG, L"Crypto Response Error: %S", Error);
	}

	m_KeyExchanges.erase(I);

	if(pCryptoKey)
	{
		pChannel->Encrypt(pCryptoKey.Detache());
		pChannel->SetQueueLock(false); // release the packet queue lock such that we can start sending encrypted payload packets
	}
}
Example #2
0
void CKadHandler::HandleCryptoRequest(const CVariant& Request, CKadNode* pNode, CComChannel* pChannel)
{
	SKadData* pData = pChannel->GetData<SKadData>();
	if(GetParent<CKademlia>()->Cfg()->GetBool("DebugTL"))
		LogLine(LOG_DEBUG, L"Recived 'CryptoRequest' to %s", pNode->GetID().ToHex().c_str());

	CVariant Response(CVariant::EMap);

	CScoped<CSymmetricKey> pCryptoKey;
	try
	{
		CScoped<CAbstractKey> pSessionKey;
		if(Request.Has("EK"))
		{
			UINT eExAlgorithm = 0;
			string Param;
			if(Request.Has("KA"))
				eExAlgorithm = ParseKA(Request["KA"], Param);
			UINT eAlgorithm = PrepKA(eExAlgorithm, Param);
			CScoped<CKeyExchange> pKeyExchange = NewKeyExchange(eAlgorithm, Param);

			CScoped<CAbstractKey> pKey = pKeyExchange->InitialsieKeyExchange();
			Response["EK"] = CVariant(pKey->GetKey(), pKey->GetSize());

			CScoped<CAbstractKey> pRemKey = new CAbstractKey(Request["EK"].GetData(), Request["EK"].GetSize());
			pSessionKey = pKeyExchange->FinaliseKeyExchange(pRemKey);
			if(!pSessionKey)
				throw "ExchangeFailed";

			bool bAuthenticated = Request.IsSigned();
			if(bAuthenticated)
			{
				CPublicKey* pPubKey;
				if(Request.Has("PK"))
					pPubKey = pNode->SetIDKey(Request);
				else
					pPubKey = pNode->GetID().GetKey();
			
				if(!pPubKey)
					throw "MissingKey";

				if(!Request.Verify(pPubKey))
					throw "InvalidSign";
			}

			pData->Authenticated = bAuthenticated;
			pNode->SetTrustedKey(new CTrustedKey(pSessionKey->GetKey(), pSessionKey->GetSize(), bAuthenticated, eAlgorithm & CAbstractKey::eHashFunkt));
		}
		else if(Request.Has("FP"))
		{
			CTrustedKey* pTrustedKey = pNode->GetTrustedKey();
			if(!pTrustedKey || pTrustedKey->GetFingerPrint() != Request["FP"].To<uint64>())
				throw "UnknownKey";

			pData->Authenticated = pTrustedKey->IsAuthenticated();
			pSessionKey = new CAbstractKey(pTrustedKey->GetKey(), pTrustedKey->GetSize());
		}
		else
			throw "UnknownMethod";

		if(Request.Has("IV"))
		{
			CAbstractKey OutIV(KEY_128BIT, true);
			Response["IV"] = CVariant(OutIV.GetKey(), OutIV.GetSize());

			UINT eSymAlgorithm = 0;
			if(Request.Has("SC"))
				eSymAlgorithm = ParseSC(Request["SC"]);
			UINT eAlgorithm = PrepSC(eSymAlgorithm);

			CAbstractKey InIV(Request["IV"].GetData(), Request["IV"].GetSize());

			pCryptoKey = NewSymmetricKey(eAlgorithm, pSessionKey, &InIV, &OutIV);
		}

		if(Request.IsSigned() && pData->Authenticated)
		{
			const CMyKadID& MyID = GetParent<CKademlia>()->Root()->GetID();
			Response["PK"] = CVariant(MyID.GetKey()->GetKey(), MyID.GetKey()->GetSize());
			if((MyID.GetKey()->GetAlgorithm() & CAbstractKey::eHashFunkt) != 0)
				Response["HK"] = CAbstractKey::Algorithm2Str((MyID.GetKey()->GetAlgorithm() & CAbstractKey::eHashFunkt));
		
			Response.Sign(MyID.GetPrivateKey());
		}
	}
	catch(const char* Error)
	{
		delete pCryptoKey.Detache();
		Response["ERR"] = Error;
	}

	if(GetParent<CKademlia>()->Cfg()->GetBool("DebugTL"))
		LogLine(LOG_DEBUG, L"Sending 'CryptoResponse' to %s", pNode->GetID().ToHex().c_str());
	pChannel->SendPacket(KAD_CRYPTO_RESPONSE, Response);

	if(pCryptoKey)
	{
		pChannel->SetQueueLock(true);
		pChannel->Encrypt(pCryptoKey.Detache());
		pChannel->SetQueueLock(false);
	}
}