Example #1
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);
	}
}