Example #1
0
void CKnownFileList::AddCancelledFileID(const uchar* hash){
	if (thePrefs.IsRememberingCancelledFiles()){
		if (m_dwCancelledFilesSeed == 0) {
			m_dwCancelledFilesSeed = (GetRandomUInt32() % 0xFFFFFFFE) + 1;
		}
		uchar pachSeedHash[20];
		PokeUInt32(pachSeedHash, m_dwCancelledFilesSeed);
		md4cpy(pachSeedHash + 4, hash);
		MD5Sum md5(pachSeedHash, sizeof(pachSeedHash));
		md4cpy(pachSeedHash, md5.GetRawHash()); 
		m_mapCancelledFiles.SetAt(CSKey(pachSeedHash), 1);	
	}
}
Example #2
0
void CFriend::SetLinkedClient(CUpDownClient* linkedClient) {
    if(linkedClient != m_LinkedClient) {
        if(linkedClient != NULL) {
            if(m_LinkedClient == NULL) {
                linkedClient->SetFriendSlot(m_friendSlot);
            } else {
                linkedClient->SetFriendSlot(m_LinkedClient->GetFriendSlot());
            }

            m_dwLastSeen = time(NULL);
            m_dwLastUsedIP = linkedClient->GetIP();
            m_nLastUsedPort = linkedClient->GetUserPort();
            m_strName = linkedClient->GetUserName();
            md4cpy(m_abyUserhash,linkedClient->GetUserHash());
            m_dwHasHash = md4cmp(m_abyUserhash, sm_abyNullHash) ? 1 : 0;

            linkedClient->m_Friend = this;
        } else if(m_LinkedClient != NULL) {
            m_friendSlot = m_LinkedClient->GetFriendSlot();
        }

        if(m_LinkedClient != NULL) {
            // the old client is no longer friend, since it is no longer the linked client
            m_LinkedClient->SetFriendSlot(false);
            m_LinkedClient->m_Friend = NULL;
        }

        m_LinkedClient = linkedClient;
    }

    theApp.friendlist->RefreshFriend(this);
}
Example #3
0
void CFriend::LoadFromFile(CFileDataIO* file)
{
	file->ReadHash16(m_abyUserhash);
	m_dwLastUsedIP = file->ReadUInt32();
	m_nLastUsedPort = file->ReadUInt16();
	m_dwLastSeen = ConvertFromTime32(file->ReadUInt32());
	m_dwLastChatted = file->ReadUInt32();

	UINT tagcount = file->ReadUInt32();
	for (UINT j = 0; j < tagcount; j++){
		CTag* newtag = new CTag(file, false);
		switch (newtag->GetNameID()){
			case FF_NAME:{
				ASSERT( newtag->IsStr() );
				if (newtag->IsStr()){
					if (m_strName.IsEmpty())
						m_strName = newtag->GetStr();
				}
				break;
			}
			case FF_KADID:{
				ASSERT( newtag->IsHash() );
				if (newtag->IsHash())
					md4cpy(m_abyKadID, newtag->GetHash());
				break;
			}
		}
		delete newtag;
	}
}
Example #4
0
CTag::CTag(const CTag& rTag)
{
	m_uType = rTag.m_uType;
	m_uName = rTag.m_uName;
	m_pszName = rTag.m_pszName!=NULL ? nstrdup(rTag.m_pszName) : NULL;
	m_nBlobSize = 0;
	if (rTag.IsStr())
		m_pstrVal = new CString(rTag.GetStr());
	else if (rTag.IsInt())
		m_uVal = rTag.GetInt();
	else if (rTag.IsFloat())
		m_fVal = rTag.GetFloat();
	else if (rTag.IsHash()){
		m_pData = new BYTE[16];
		md4cpy(m_pData, rTag.GetHash());
	}
	else if (rTag.IsBlob()){
		m_nBlobSize = rTag.GetBlobSize();
		m_pData = new BYTE[rTag.GetBlobSize()];
		memcpy(m_pData, rTag.GetBlob(), rTag.GetBlobSize());
	}
	else{
		ASSERT(0);
		m_uVal = 0;
	}
	ASSERT_VALID(this);
}
Example #5
0
bool CKnownFileList::IsCancelledFileByID(const uchar* hash) const
{
	if (thePrefs.IsRememberingCancelledFiles()){
		uchar pachSeedHash[20];
		PokeUInt32(pachSeedHash, m_dwCancelledFilesSeed);
		md4cpy(pachSeedHash + 4, hash);
		MD5Sum md5(pachSeedHash, sizeof(pachSeedHash));
		md4cpy(pachSeedHash, md5.GetRawHash()); 

		int dwDummy;
		if (m_mapCancelledFiles.Lookup(CSKey(pachSeedHash), dwDummy)){
			return true;
		}
	}
	return false;
}
bool CCollectionFile::InitFromLink(CString sLink)
{
	CED2KLink* pLink = NULL;
	CED2KFileLink* pFileLink = NULL;
	try 
	{
		pLink = CED2KLink::CreateLinkFromUrl(sLink);
		if(!pLink)
			throw GetResString(IDS_ERR_NOTAFILELINK);
		pFileLink = pLink->GetFileLink();
		if (!pFileLink)
			throw GetResString(IDS_ERR_NOTAFILELINK);
	} 
	catch (CString error) 
	{
		CString strBuffer;
		strBuffer.Format(GetResString(IDS_ERR_INVALIDLINK),error);
		LogError(LOG_STATUSBAR, GetResString(IDS_ERR_LINKERROR), strBuffer);
		return false;
	}

	taglist.Add(new CTag(FT_FILEHASH, pFileLink->GetHashKey()));
	md4cpy(m_abyFileHash, pFileLink->GetHashKey());

	taglist.Add(new CTag(FT_FILESIZE, pFileLink->GetSize()));
	SetFileSize(pFileLink->GetSize());

	taglist.Add(new CTag(FT_FILENAME, pFileLink->GetName()));
	SetFileName(pFileLink->GetName(), false, false);

	delete pLink;
	return true;
}
Example #7
0
void CFriend::WriteToFile(CFileDataIO* file)
{
	if (!m_dwHasHash)
		md4cpy(m_abyUserhash, sm_abyNullHash);
	file->WriteHash16(m_abyUserhash);
	file->WriteUInt32(m_dwLastUsedIP);
	file->WriteUInt16(m_nLastUsedPort);
	file->WriteUInt32(m_dwLastSeen);
	file->WriteUInt32(m_dwLastChatted);

	uint32 uTagCount = 0;
	ULONG uTagCountFilePos = (ULONG)file->GetPosition();
	file->WriteUInt32(uTagCount);

	if (!m_strName.IsEmpty()){
		if (WriteOptED2KUTF8Tag(file, m_strName, FF_NAME))
			uTagCount++;
		CTag nametag(FF_NAME, m_strName);
		nametag.WriteTagToFile(file);
		uTagCount++;
	}

	file->Seek(uTagCountFilePos, CFile::begin);
	file->WriteUInt32(uTagCount);
	file->Seek(0, CFile::end);
}
Example #8
0
CDeadSource::CDeadSource(const uchar* paucHash){
	m_dwID = 0;
	m_dwServerIP = 0;
	m_nPort = 0;
	m_nKadPort = 0;
	md4cpy(m_aucHash, paucHash);

}
Example #9
0
CDeadSource& CDeadSource::operator=(const CDeadSource& ds){
	m_dwID = ds.m_dwID;
	m_dwServerIP = ds.m_dwServerIP;
	m_nPort = ds.m_nPort;
	m_nKadPort = ds.m_nKadPort;
	md4cpy(m_aucHash, ds.m_aucHash);
	return *this;
}
Example #10
0
//Added this to work with the IRC.. Probably a better way to do it.. But wanted this in the release..
CFriend::CFriend(const uchar* abyUserhash, uint32 dwLastSeen, uint32 dwLastUsedIP, uint32 nLastUsedPort, 
				 uint32 dwLastChatted, LPCTSTR pszName, uint32 dwHasHash){
	m_dwLastSeen = dwLastSeen;
	m_dwLastUsedIP = dwLastUsedIP;
	m_nLastUsedPort = nLastUsedPort;
	m_dwLastChatted = dwLastChatted;
	if( dwHasHash && abyUserhash){
		md4cpy(m_abyUserhash,abyUserhash);
		m_dwHasHash = md4cmp(m_abyUserhash, sm_abyNullHash) ? 1 : 0;
	}
	else{
		md4cpy(m_abyUserhash, sm_abyNullHash);
		m_dwHasHash = 0;
	}
	m_strName = pszName;
	m_LinkedClient = 0;
    m_friendSlot = false;
}
void KadUtilityFunctions::HashData(byte* in_string,UINT in_string_len,byte *output)
{
	// time critial
	md4clr(output);
	bool PaddingStarted = false;
	UINT Hash[4];
	Hash[0] = 0x67452301;
	Hash[1] = 0xEFCDAB89;
	Hash[2] = 0x98BADCFE;
	Hash[3] = 0x10325476;
	CFile* data = 0;
	if (in_string)
		data = new CMemFile(in_string,in_string_len);
	UINT Required = in_string_len;
	byte   X[64*128];  
	while (Required >= 64){
        UINT len = Required / 64; 
        if (len > sizeof(X)/(64 * sizeof(X[0]))) 
             len = sizeof(X)/(64 * sizeof(X[0])); 

		data->Read(&X,len*64);

		for (UINT i = 0; i < len; i++) 
        { 
           MD4Transform(Hash, (UINT*)(X + i*64)); 
        }
		Required -= len*64;
	}
	// bytes to read
	Required = in_string_len % 64;
	if (Required != 0){
		data->Read(&X,Required);
	}
	// in byte scale 512 = 64, 448 = 56
	if (Required >= 56){
		X[Required] = 0x80;
		PaddingStarted = TRUE;
		memset(&X[Required + 1], 0, 63 - Required);
		MD4Transform(Hash, (UINT*)X);
		Required = 0;
	}
	if (!PaddingStarted)
		X[Required++] = 0x80;
	memset(&X[Required], 0, 64 - Required);
	// add size (convert to bits)
	UINT in_string_len2 = in_string_len >> 29;
	in_string_len <<= 3;
	memcpy(&X[56], &in_string_len, 4);
	memcpy(&X[60], &in_string_len2, 4);
	MD4Transform(Hash, (UINT*)X);
	md4cpy(output, Hash);
	if(data!=NULL){
		delete data;
	}
	//safe_delete(data);
}
Example #12
0
CTag::CTag(uint8 uName, const BYTE* pucHash)
{
	m_uType = TAGTYPE_HASH;
	m_uName = uName;
	m_pszName = NULL;
	m_pData = new BYTE[16];
	md4cpy(m_pData, pucHash);
	m_nBlobSize = 0;
	ASSERT_VALID(this);
}
int CEncryptedDatagramSocket::DecryptReceivedClient(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwIP) const{
	int nResult = nBufLen;
	*ppbyBufOut = pbyBufIn;
	
	if (nResult <= CRYPT_HEADER_WITHOUTPADDING || !thePrefs.IsClientCryptLayerSupported())
		return nResult;
	
	switch (pbyBufIn[0]){
		case OP_EMULEPROT:
		case OP_KADEMLIAPACKEDPROT:
		case OP_KADEMLIAHEADER:
		case OP_UDPRESERVEDPROT1:
		case OP_UDPRESERVEDPROT2:
		case OP_PACKEDPROT:
			return nResult; // no encrypted packet (see description on top)
	}
	// might be an encrypted packet, try to decrypt
	uchar achKeyData[23];
	md4cpy(achKeyData, thePrefs.GetUserHash());
	achKeyData[20] = MAGICVALUE_UDP;
	memcpy(achKeyData + 16, &dwIP, 4);
	memcpy(achKeyData + 21, pbyBufIn + 1, 2); // random key part sent from remote client
	MD5Sum md5(achKeyData, sizeof(achKeyData));
	RC4_Key_Struct keyReceiveKey;
	RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true);
	
	uint32 dwValue;
	RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey);
	if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT){
		// yup this is an encrypted packet
		DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s"), ipstr(dwIP)) );
		uint8 byPadLen;
		RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey);
		nResult -= CRYPT_HEADER_WITHOUTPADDING;
		if (nResult <= byPadLen){
			DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen);
			return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk
		}
		if (byPadLen > 0)
			RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey);
		nResult -= byPadLen;
		*ppbyBufOut = pbyBufIn + (nBufLen - nResult);
		RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey);
		
		theStats.AddDownDataOverheadCrypt(nBufLen - nResult);
		return nResult; // done
	}
	else{
		DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP));
		return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk
	}
}
Example #14
0
CFriend::CFriend(void)
{
	m_dwLastSeen = 0;
	m_dwLastUsedIP = 0;
	m_nLastUsedPort = 0;
	m_dwLastChatted = 0;
	(void)m_strName;
	m_LinkedClient = 0;
	md4cpy(m_abyUserhash, sm_abyNullHash);
	m_dwHasHash = 0;

    m_friendSlot = false;
}
Example #15
0
CFriend::CFriend(CUpDownClient* client){
	ASSERT ( client );
	m_dwLastSeen = time(NULL);
	m_dwLastUsedIP = client->GetIP();
	m_nLastUsedPort = client->GetUserPort();
	m_dwLastChatted = 0;
    m_LinkedClient = NULL;
    m_friendSlot = false;
	m_FriendConnectState = FCS_NONE;
	m_dwLastKadSearch = 0;
	md4clr(m_abyKadID);
	md4cpy(m_abyUserhash, client->GetUserHash());
    SetLinkedClient(client);
}
Example #16
0
void CFriend::KadSearchNodeIDByIPResult(Kademlia::EKadClientSearchRes eStatus, const uchar* pachNodeID){
	if (!theApp.friendlist->IsValid(this))
	{
		ASSERT( false );
		return;
	}
	if (eStatus == Kademlia::KCSR_SUCCEEDED){
		ASSERT( pachNodeID != NULL );
		DebugLog(_T("Successfully fetched KadID (%s) for friend %s"), md4str(pachNodeID), m_strName.IsEmpty() ? _T("(Unknown)") : m_strName);
		md4cpy(m_abyKadID, pachNodeID);
	}
	else
		DebugLog(_T("Failed to fetch KadID for friend %s (%s)"), m_strName.IsEmpty() ? _T("(Unknown)") : m_strName, ipstr(m_dwLastUsedIP));
}
Example #17
0
CAbstractFile::CAbstractFile(const CAbstractFile* pAbstractFile)
{
	m_strFileName = pAbstractFile->m_strFileName;
	md4cpy(m_abyFileHash, pAbstractFile->GetFileHash());
	m_nFileSize = pAbstractFile->m_nFileSize;
	m_strComment = pAbstractFile->m_strComment;
	m_uRating = pAbstractFile->m_uRating;
	m_bCommentLoaded = pAbstractFile->m_bCommentLoaded;
	m_uUserRating = pAbstractFile->m_uUserRating;
	m_bHasComment = pAbstractFile->m_bHasComment;
	m_strFileType = pAbstractFile->m_strFileType;

	CopyTags(pAbstractFile->GetTags());
}
Example #18
0
//Added this to work with the IRC.. Probably a better way to do it.. But wanted this in the release..
CFriend::CFriend(const uchar* abyUserhash, uint32_t dwLastSeen, uint32_t dwLastUsedIP, uint16_t nLastUsedPort, 
				 uint32_t dwLastChatted, LPCTSTR pszName, uint32_t dwHasHash){
	m_dwLastSeen = dwLastSeen;
	m_dwLastUsedIP = dwLastUsedIP;
	m_nLastUsedPort = nLastUsedPort;
	m_dwLastChatted = dwLastChatted;
	if(dwHasHash && abyUserhash){
		md4cpy(m_abyUserhash,abyUserhash);
	}
	else
		md4clr(m_abyUserhash);
	md4clr(m_abyKadID);
	m_strName = pszName;
	m_LinkedClient = 0;
    m_friendSlot = false;
	m_FriendConnectState = FCS_NONE;
	m_dwLastKadSearch = 0;
}
Example #19
0
void CMuleUDPSocket::SendPacket(CPacket* packet, uint32 IP, uint16 port, bool bEncrypt, const uint8* pachTargetClientHashORKadID, bool bKad, uint32 nReceiverVerifyKey)
{
	wxCHECK_RET(packet, wxT("Invalid packet."));
	/*wxCHECK_RET(port, wxT("Invalid port."));
	wxCHECK_RET(IP, wxT("Invalid IP."));
	*/

	if (!port || !IP) {
		return;
	}

	if (!Ok()) {
		AddDebugLogLineN(logMuleUDP, (m_name + wxT(": Packet discarded, socket not Ok ("))
			<< Uint32_16toStringIP_Port(IP, port) << wxT("): ") << packet->GetPacketSize() << wxT("b"));
		delete packet;

		return;
	}

	AddDebugLogLineN(logMuleUDP, (m_name + wxT(": Packet queued ("))
		<< Uint32_16toStringIP_Port(IP, port) << wxT("): ") << packet->GetPacketSize() << wxT("b"));

	UDPPack newpending;
	newpending.IP = IP;
	newpending.port = port;
	newpending.packet = packet;
	newpending.time = GetTickCount();
	newpending.bEncrypt = bEncrypt && (pachTargetClientHashORKadID != NULL || (bKad && nReceiverVerifyKey != 0))
							&& thePrefs::IsClientCryptLayerSupported();
	newpending.bKad = bKad;
	newpending.nReceiverVerifyKey = nReceiverVerifyKey;
	if (newpending.bEncrypt && pachTargetClientHashORKadID != NULL) {
		md4cpy(newpending.pachTargetClientHashORKadID, pachTargetClientHashORKadID);
	} else {
		md4clr(newpending.pachTargetClientHashORKadID);
	}

	{
		wxMutexLocker lock(m_mutex);
		m_queue.push_back(newpending);
	}

	theApp->uploadBandwidthThrottler->QueueForSendingControlPacket(this);
}
Example #20
0
CAbstractFile::CAbstractFile(const CAbstractFile* pAbstractFile)
{
	m_strFileName = pAbstractFile->m_strFileName;
	md4cpy(m_abyFileHash, pAbstractFile->GetFileHash());
	m_nFileSize = pAbstractFile->m_nFileSize;
	m_strComment = pAbstractFile->m_strComment;
	m_uRating = pAbstractFile->m_uRating;
	m_bCommentLoaded = pAbstractFile->m_bCommentLoaded;
	m_uUserRating = pAbstractFile->m_uUserRating;
	m_bHasComment = pAbstractFile->m_bHasComment;
	m_strFileType = pAbstractFile->m_strFileType;
	m_bKadCommentSearchRunning = pAbstractFile->m_bKadCommentSearchRunning;

	const CTypedPtrList<CPtrList, Kademlia::CEntry*>& list = pAbstractFile->getNotes();
	for(POSITION pos = list.GetHeadPosition(); pos != NULL; )
	{
			Kademlia::CEntry* entry = list.GetNext(pos);
			m_kadNotes.AddTail(entry->Copy());
	}

	CopyTags(pAbstractFile->GetTags());
}
void CEncryptedStreamSocket::SetConnectionEncryption(bool bEnabled, const uchar* pTargetClientHash, bool bServerConnection){
	if (m_StreamCryptState != ECS_UNKNOWN && m_StreamCryptState != ECS_NONE){
		if (!m_StreamCryptState == ECS_NONE || bEnabled)
			ASSERT( false );
		return;
	}
	ASSERT( m_pRC4SendKey == NULL );
	ASSERT( m_pRC4ReceiveKey == NULL );

	if (bEnabled && pTargetClientHash != NULL && !bServerConnection){
		m_StreamCryptState = ECS_PENDING;
		// create obfuscation keys, see on top for key format

		// use the crypt random generator
		m_nRandomKeyPart = cryptRandomGen.GenerateWord32();

		uchar achKeyData[21];
		md4cpy(achKeyData, pTargetClientHash);
		memcpy(achKeyData + 17, &m_nRandomKeyPart, 4);
		
		achKeyData[16] = MAGICVALUE_REQUESTER;
		MD5Sum md5(achKeyData, sizeof(achKeyData));
		m_pRC4SendKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);

		achKeyData[16] = MAGICVALUE_SERVER;
		md5.Calculate(achKeyData, sizeof(achKeyData));
		m_pRC4ReceiveKey = RC4CreateKey(md5.GetRawHash(), 16, NULL);
	}
	else if (bServerConnection && bEnabled){
		m_bServerCrypt = true;
		m_StreamCryptState = ECS_PENDING_SERVER;
	}
	else{
		ASSERT( !bEnabled );
		m_StreamCryptState = ECS_NONE;
	}
}
Example #22
0
void CEncryptedStreamSocket::SetConnectionEncryption(bool bEnabled, const uint8_t* pTargetClientHash, bool bServerConnection)
{
	if (m_StreamCryptState != ECS_UNKNOWN && m_StreamCryptState != ECS_NONE) {
		if (!m_StreamCryptState == ECS_NONE || bEnabled) {
			wxFAIL;
		}
		return;
	}

	if (bEnabled && pTargetClientHash != NULL && !bServerConnection) {
		m_StreamCryptState = ECS_PENDING;
		// create obfuscation keys, see on top for key format

		// use the crypt random generator
		m_nRandomKeyPart = GetRandomUint32();

		uint8 achKeyData[21];
		md4cpy(achKeyData, pTargetClientHash);
		PokeUInt32(achKeyData + 17, m_nRandomKeyPart);

		achKeyData[16] = MAGICVALUE_REQUESTER;
		MD5Sum md5(achKeyData, sizeof(achKeyData));
		m_pfiSendBuffer.SetKey(md5);

		achKeyData[16] = MAGICVALUE_SERVER;
		md5.Calculate(achKeyData, sizeof(achKeyData));
		m_pfiReceiveBuffer.SetKey(md5);

	} else if (bServerConnection && bEnabled) {
		//printf("->Server crypt\n");
		m_bServerCrypt = true;
		m_StreamCryptState = ECS_PENDING_SERVER;
	} else {
		wxASSERT( !bEnabled );
		m_StreamCryptState = ECS_NONE;
	}
}
Example #23
0
// Encrypt packet. Key used:
// clientHashOrKadID != NULL					-> clientHashOrKadID
// clientHashOrKadID == NULL && kad && receiverVerifyKey != 0	-> receiverVerifyKey
// else								-> ASSERT
int CEncryptedDatagramSocket::EncryptSendClient(uint8_t **buf, int bufLen, const uint8_t *clientHashOrKadID, bool kad, uint32_t receiverVerifyKey, uint32_t senderVerifyKey)
{
	wxASSERT(theApp->GetPublicIP() != 0 || kad);
	wxASSERT(thePrefs::IsClientCryptLayerSupported());
	wxASSERT(clientHashOrKadID != NULL || receiverVerifyKey != 0);
	wxASSERT((receiverVerifyKey == 0 && senderVerifyKey == 0) || kad);

	uint8_t padLen = 0;			// padding disabled for UDP currently
	const uint32_t cryptHeaderLen = padLen + CRYPT_HEADER_WITHOUTPADDING + (kad ? 8 : 0);
	uint32_t cryptedLen = bufLen + cryptHeaderLen;
	uint8_t *cryptedBuffer = new uint8_t[cryptedLen];
	bool kadRecvKeyUsed = false;

	uint16_t randomKeyPart = GetRandomUint16();
	CRC4EncryptableBuffer sendbuffer;
	MD5Sum md5;
	if (kad) {
		if ((clientHashOrKadID == NULL || CMD4Hash(clientHashOrKadID).IsEmpty()) && receiverVerifyKey != 0) {
			kadRecvKeyUsed = true;
			uint8_t keyData[6];
			PokeUInt32(keyData, receiverVerifyKey);
			PokeUInt16(keyData+4, randomKeyPart);
			md5.Calculate(keyData, sizeof(keyData));
			//DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) );
		}
		else if (clientHashOrKadID != NULL && !CMD4Hash(clientHashOrKadID).IsEmpty()) {
			uint8_t keyData[18];
			md4cpy(keyData, clientHashOrKadID);
			PokeUInt16(keyData+16, randomKeyPart);
			md5.Calculate(keyData, sizeof(keyData));
			//DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) );
		}
		else {
			delete [] cryptedBuffer;
			wxFAIL;
			return bufLen;
		}
	} else {
		uint8_t keyData[23];
		md4cpy(keyData, clientHashOrKadID);
		PokeUInt32(keyData+16, theApp->GetPublicIP());
		PokeUInt16(keyData+21, randomKeyPart);
		keyData[20] = MAGICVALUE_UDP;
		md5.Calculate(keyData, sizeof(keyData));
	}

	sendbuffer.SetKey(md5, true);

	// create the semi random byte encryption header
	uint8_t semiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++) {
		semiRandomNotProtocolMarker = GetRandomUint8();
		semiRandomNotProtocolMarker = kad ? (semiRandomNotProtocolMarker & 0xFE) : (semiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit
		if (kad) {
			// set the ed2k/kad and nodeid/recvkey markerbit
			semiRandomNotProtocolMarker = kadRecvKeyUsed ? ((semiRandomNotProtocolMarker & 0xFE) | 0x02) : (semiRandomNotProtocolMarker & 0xFC);
		} else {
			// set the ed2k/kad marker bit
			semiRandomNotProtocolMarker = (semiRandomNotProtocolMarker | 0x01);
		}

		bool bOk = false;
		switch (semiRandomNotProtocolMarker) { // not allowed values
			case OP_EMULEPROT:
			case OP_KADEMLIAPACKEDPROT:
			case OP_KADEMLIAHEADER:
			case OP_UDPRESERVEDPROT1:
			case OP_UDPRESERVEDPROT2:
			case OP_PACKEDPROT:
				break;
			default:
				bOk = true;
		}

		if (bOk) {
			break;
		}
	}

	if (i >= 128) {
		// either we have _real_ bad luck or the randomgenerator is a bit messed up
		wxFAIL;
		semiRandomNotProtocolMarker = 0x01;
	}

	cryptedBuffer[0] = semiRandomNotProtocolMarker;
	PokeUInt16(cryptedBuffer + 1, randomKeyPart);

	uint32_t magicValue = ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_CLIENT);
	sendbuffer.RC4Crypt((uint8_t*)&magicValue, cryptedBuffer + 3, 4);
	sendbuffer.RC4Crypt((uint8_t*)&padLen, cryptedBuffer + 7, 1);

	for (int j = 0; j < padLen; j++) {
		uint8_t byRand = (uint8_t)rand();	// they actually don't really need to be random, but it doesn't hurt either
		sendbuffer.RC4Crypt((uint8_t*)&byRand, cryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1);
	}

	if (kad) {
		ENDIAN_SWAP_I_32(receiverVerifyKey);
		ENDIAN_SWAP_I_32(senderVerifyKey);
		sendbuffer.RC4Crypt((uint8_t*)&receiverVerifyKey, cryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + padLen, 4);
		sendbuffer.RC4Crypt((uint8_t*)&senderVerifyKey, cryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + padLen + 4, 4);
	}

	sendbuffer.RC4Crypt(*buf, cryptedBuffer + cryptHeaderLen, bufLen);
	delete [] *buf;
	*buf = cryptedBuffer;

	theStats::AddUpOverheadCrypt(cryptedLen - bufLen);
	return cryptedLen;
}
Example #24
0
void CAbstractFile::SetFileHash(const uchar* pucFileHash)
{
	md4cpy(m_abyFileHash, pucFileHash);
}
Example #25
0
//from emule
void DonkeyFile::CreateHashFromInput(FILE* file,CFile* file2, int Length, byte* Output, byte* in_string)
{
    // time critial
    md4clr(Output);
    bool PaddingStarted = false;
    UINT Hash[4];
    Hash[0] = 0x67452301;
    Hash[1] = 0xEFCDAB89;
    Hash[2] = 0x98BADCFE;
    Hash[3] = 0x10325476;
    CFile* data = 0;
    if (in_string)
        data = new CMemFile(in_string,Length);
    UINT Required = Length;
    byte   X[64*128];
    while (Required >= 64) {
        UINT len = Required / 64;
        if (len > sizeof(X)/(64 * sizeof(X[0])))
            len = sizeof(X)/(64 * sizeof(X[0]));
        if (in_string)
            data->Read(&X,len*64);
        else if (file)
            fread(&X,len*64,1,file);
        else if (file2)
            file2->Read(&X,len*64);
        for (UINT i = 0; i < len; i++)
        {
            MD4Transform(Hash, (UINT*)(X + i*64));
        }
        Required -= len*64;
    }
    // bytes to read
    Required = Length % 64;
    if (Required != 0) {
        if (in_string)
            data->Read(&X,Required);
        else if (file)
            fread(&X,Required,1,file);
        else if (file2)
            file2->Read(&X,Required);
    }
    // in byte scale 512 = 64, 448 = 56
    if (Required >= 56) {
        X[Required] = 0x80;
        PaddingStarted = TRUE;
        memset(&X[Required + 1], 0, 63 - Required);
        MD4Transform(Hash, (UINT*)X);
        Required = 0;
    }
    if (!PaddingStarted)
        X[Required++] = 0x80;
    memset(&X[Required], 0, 64 - Required);
    // add size (convert to bits)
    UINT Length2 = Length >> 29;
    Length <<= 3;
    memcpy(&X[56], &Length, 4);
    memcpy(&X[60], &Length2, 4);
    MD4Transform(Hash, (UINT*)X);
    md4cpy(Output, Hash);
    if(data!=NULL) {
        delete data;
    }
    //safe_delete(data);
}
// Encrypt packet. Key used:
// pachClientHashOrKadID != NULL									-> pachClientHashOrKadID
// pachClientHashOrKadID == NULL && bKad && nReceiverVerifyKey != 0 -> nReceiverVerifyKey
// else																-> ASSERT
int CEncryptedDatagramSocket::EncryptSendClient(uchar** ppbyBuf, int nBufLen, const uchar* pachClientHashOrKadID, bool bKad, uint32 nReceiverVerifyKey, uint32 nSenderVerifyKey) const{
	ASSERT( theApp.GetPublicIP() != 0 || bKad );
	ASSERT( thePrefs.IsClientCryptLayerSupported() );
	ASSERT( pachClientHashOrKadID != NULL || nReceiverVerifyKey != 0 );
	ASSERT( (nReceiverVerifyKey == 0 && nSenderVerifyKey == 0) || bKad );

	uint8 byPadLen = 0;			// padding disabled for UDP currently
	const uint32 nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 8 : 0);
	
	uint32 nCryptedLen = nBufLen + nCryptHeaderLen;
	uchar* pachCryptedBuffer = new uchar[nCryptedLen];
	bool bKadRecKeyUsed = false;
	
	uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF);
	MD5Sum md5;
	if (bKad){
		if ((pachClientHashOrKadID == NULL || isnulmd4(pachClientHashOrKadID)) && nReceiverVerifyKey != 0) {
			bKadRecKeyUsed = true;
			uchar achKeyData[6];
			PokeUInt32(achKeyData, nReceiverVerifyKey);
			PokeUInt16(achKeyData+4, nRandomKeyPart);
			md5.Calculate(achKeyData, sizeof(achKeyData));
			//DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) );  
		}
		else if (pachClientHashOrKadID != NULL && !isnulmd4(pachClientHashOrKadID)) {
			uchar achKeyData[18];
			md4cpy(achKeyData, pachClientHashOrKadID);
			PokeUInt16(achKeyData+16, nRandomKeyPart);
			md5.Calculate(achKeyData, sizeof(achKeyData));
			//DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) );  
		}
		else {
			ASSERT( false );
			delete[] pachCryptedBuffer;
			return nBufLen;
		}
	}
	else{
		uchar achKeyData[23];
		md4cpy(achKeyData, pachClientHashOrKadID);
		uint32 dwIP = theApp.GetPublicIP();
		memcpy(achKeyData+16, &dwIP, 4);
		memcpy(achKeyData+21, &nRandomKeyPart, 2);
		achKeyData[20] = MAGICVALUE_UDP;
		md5.Calculate(achKeyData, sizeof(achKeyData));
	}
	RC4_Key_Struct keySendKey;
	RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true);

	// create the semi random byte encryption header
	uint8 bySemiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++){
		bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte();
		bySemiRandomNotProtocolMarker = bKad ? (bySemiRandomNotProtocolMarker & 0xFE) : (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit
		if (bKad)
			bySemiRandomNotProtocolMarker = bKadRecKeyUsed ? ((bySemiRandomNotProtocolMarker & 0xFE) | 0x02) : (bySemiRandomNotProtocolMarker & 0xFC); // set the ed2k/kad and nodeid/reckey markerbit
		else
			bySemiRandomNotProtocolMarker = (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit
		
		bool bOk = false;
		switch (bySemiRandomNotProtocolMarker){ // not allowed values
			case OP_EMULEPROT:
			case OP_KADEMLIAPACKEDPROT:
			case OP_KADEMLIAHEADER:
			case OP_UDPRESERVEDPROT1:
			case OP_UDPRESERVEDPROT2:
			case OP_PACKEDPROT:
				break;
			default:
				bOk = true;
		}
		if (bOk)
			break;
	}
	if (i >= 128){
		// either we have _really_ bad luck or the randomgenerator is a bit messed up
		ASSERT( false );
		bySemiRandomNotProtocolMarker = 0x01;
	}

	uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT;
	pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker;
	memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2);
	RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey);
	RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey);

	for (int j = 0; j < byPadLen; j++){
		uint8 byRand = (uint8)rand();	// they actually dont really need to be random, but it doesn't hurts either
		RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey);
	}

	if (bKad){
		RC4Crypt((uchar*)&nReceiverVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, 4, &keySendKey);
		RC4Crypt((uchar*)&nSenderVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4, 4, &keySendKey);
	}

	RC4Crypt(*ppbyBuf, pachCryptedBuffer + nCryptHeaderLen, nBufLen, &keySendKey);
	delete[] *ppbyBuf;
	*ppbyBuf = pachCryptedBuffer;

	//Xman
	// Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter-
	/*
	theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);
	*/
	theApp.pBandWidthControl->AddeMuleOutObfuscationUDP(nCryptedLen - nBufLen);
	//Xman end

	return nCryptedLen;
}
int CEncryptedDatagramSocket::DecryptReceivedClient(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwIP, uint32* nReceiverVerifyKey, uint32* nSenderVerifyKey) const{
	int nResult = nBufLen;
	*ppbyBufOut = pbyBufIn;
	
	if (nReceiverVerifyKey == NULL || nSenderVerifyKey == NULL){
		ASSERT( false );
		return nResult;
	}
	
	*nReceiverVerifyKey = 0;
	*nSenderVerifyKey = 0;

	if (nResult <= CRYPT_HEADER_WITHOUTPADDING /*|| !thePrefs.IsClientCryptLayerSupported()*/)
		return nResult;	

	switch (pbyBufIn[0]){
		case OP_EMULEPROT:
		case OP_KADEMLIAPACKEDPROT:
		case OP_KADEMLIAHEADER:
		case OP_UDPRESERVEDPROT1:
		case OP_UDPRESERVEDPROT2:
		case OP_PACKEDPROT:
			return nResult; // no encrypted packet (see description on top)
	}

	// might be an encrypted packet, try to decrypt
	RC4_Key_Struct keyReceiveKey;
	uint32 dwValue = 0;
	// check the marker bit which type this packet could be and which key to test first, this is only an indicator since old clients have it set random
	// see the header for marker bits explanation
	byte byCurrentTry = ((pbyBufIn[0] & 0x03) == 3) ? 1 : (pbyBufIn[0] & 0x03); 
	byte byTries;
	if (Kademlia::CKademlia::GetPrefs() == NULL) {
		// if kad never run, no point in checking anything except for ed2k encryption
		byTries = 1;
		byCurrentTry = 1;
	}
	else
		byTries = 3;
	bool bKadRecvKeyUsed = false;
	bool bKad = false;
	do{
		byTries--;
		MD5Sum md5;
		if (byCurrentTry == 0) {
			// kad packet with NodeID as key
			bKad = true;
			bKadRecvKeyUsed = false;
			if (Kademlia::CKademlia::GetPrefs()) {
				uchar achKeyData[18];
				memcpy(achKeyData, Kademlia::CKademlia::GetPrefs()->GetKadID().GetData(), 16);
				memcpy(achKeyData + 16, pbyBufIn + 1, 2); // random key part sent from remote client
				md5.Calculate(achKeyData, sizeof(achKeyData));
			}
		}
		else if (byCurrentTry == 1) {
			// ed2k packet
			bKad = false;
			bKadRecvKeyUsed = false;
			uchar achKeyData[23];
			md4cpy(achKeyData, thePrefs.GetUserHash());
			achKeyData[20] = MAGICVALUE_UDP;
			memcpy(achKeyData + 16, &dwIP, 4);
			memcpy(achKeyData + 21, pbyBufIn + 1, 2); // random key part sent from remote client
			md5.Calculate(achKeyData, sizeof(achKeyData));
		}
		else if (byCurrentTry == 2) {
			// kad packet with ReceiverKey as key
			bKad = true;
			bKadRecvKeyUsed = true;
			if (Kademlia::CKademlia::GetPrefs()) {
				uchar achKeyData[6];
				PokeUInt32(achKeyData, Kademlia::CPrefs::GetUDPVerifyKey(dwIP));
				memcpy(achKeyData + 4, pbyBufIn + 1, 2); // random key part sent from remote client
				md5.Calculate(achKeyData, sizeof(achKeyData));
			}
		}
		else
			ASSERT( false );

		RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true);
		RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey);
		byCurrentTry = (byCurrentTry + 1) % 3;
	} while (dwValue != MAGICVALUE_UDP_SYNC_CLIENT && byTries > 0); // try to decrypt as ed2k as well as kad packet if needed (max 3 rounds)
	
	if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT){
		// yup this is an encrypted packet
		// debugoutput notices
		// the following cases are "allowed" but shouldn't happen given that there is only our implementation yet
		if (bKad && (pbyBufIn[0] & 0x01) != 0)
			DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, ed2k bit)"), ipstr(dwIP));
		else if (bKad && !bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) != 0)
			DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, nodeid key, recvkey bit)"), ipstr(dwIP));
		else if (bKad && bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) == 0)
			DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, recvkey key, nodeid bit)"), ipstr(dwIP));

		uint8 byPadLen;
		RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey);
		nResult -= CRYPT_HEADER_WITHOUTPADDING;
		if (nResult <= byPadLen){
			DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen);
			return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk
		}
		if (byPadLen > 0)
			RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey);
		nResult -= byPadLen;

		if (bKad){
			if (nResult <= 8){
				DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP));
				return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk;
			}
			// read the verify keys
			RC4Crypt(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen, (uchar*)nReceiverVerifyKey, 4, &keyReceiveKey);
			RC4Crypt(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 4, (uchar*)nSenderVerifyKey, 4, &keyReceiveKey);
			nResult -= 8;
		}
		*ppbyBufOut = pbyBufIn + (nBufLen - nResult);
		RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey);
		//Xman
		// Maella -Accurate measure of bandwidth: eDonkey data + control, network adapter-
		/*
		theStats.AddDownDataOverheadCrypt(nBufLen - nResult);
		*/
		theApp.pBandWidthControl->AddeMuleInObfuscation(nBufLen - nResult);
		//Xman end
		//DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s, Key: %s, RKey: %u, SKey: %u"), ipstr(dwIP), bKad ? (bKadRecvKeyUsed ? _T("ReceiverKey") : _T("NodeID")) : _T("UserHash")
		//	, nReceiverVerifyKey != 0 ? *nReceiverVerifyKey : 0, nSenderVerifyKey != 0 ? *nSenderVerifyKey : 0) );
		return nResult; // done
	}
	else{
		DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s, Possible RecvKey: %u"), ipstr(dwIP), Kademlia::CPrefs::GetUDPVerifyKey(dwIP));
		return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk
	}
}
Example #28
0
int CEncryptedDatagramSocket::DecryptReceivedClient(uint8_t *bufIn, int bufLen, uint8_t **bufOut, uint32_t ip, uint32_t *receiverVerifyKey, uint32_t *senderVerifyKey)
{
	int result = bufLen;
	*bufOut = bufIn;

	if (receiverVerifyKey == NULL || senderVerifyKey == NULL) {
		wxFAIL;
		return result;
	}

	*receiverVerifyKey = 0;
	*senderVerifyKey = 0;

	if (result <= CRYPT_HEADER_WITHOUTPADDING /*|| !thePrefs.IsClientCryptLayerSupported()*/) {
		return result;
	}

	switch (bufIn[0]) {
		case OP_EMULEPROT:
		case OP_KADEMLIAPACKEDPROT:
		case OP_KADEMLIAHEADER:
		case OP_UDPRESERVEDPROT1:
		case OP_UDPRESERVEDPROT2:
		case OP_PACKEDPROT:
			return result; // no encrypted packet (see description on top)
		default:
			;
	}

	// might be an encrypted packet, try to decrypt
	CRC4EncryptableBuffer receivebuffer;
	uint32_t value = 0;
	// check the marker bit which type this packet could be and which key to test first, this is only an indicator since old clients have it set random
	// see the header for marker bits explanation
	uint8_t currentTry = ((bufIn[0] & 0x03) == 3) ? 1 : (bufIn[0] & 0x03);
	uint8_t tries;
	if (Kademlia::CKademlia::GetPrefs() == NULL) {
		// if kad never run, no point in checking anything except for ed2k encryption
		tries = 1;
		currentTry = 1;
	} else {
		tries = 3;
	}
	bool kad = false;
	do {
		receivebuffer.FullReset();
		tries--;
		MD5Sum md5;

		if (currentTry == 0) {
			// kad packet with NodeID as key
			kad = true;
			if (Kademlia::CKademlia::GetPrefs()) {
				uint8_t keyData[18];
				Kademlia::CKademlia::GetPrefs()->GetKadID().StoreCryptValue((uint8_t *)&keyData);
				memcpy(keyData + 16, bufIn + 1, 2); // random key part sent from remote client
				md5.Calculate(keyData, sizeof(keyData));
			}
		} else if (currentTry == 1) {
			// ed2k packet
			kad = false;
			uint8_t keyData[23];
			md4cpy(keyData, thePrefs::GetUserHash().GetHash());
			keyData[20] = MAGICVALUE_UDP;
			PokeUInt32(keyData + 16, ip);
			memcpy(keyData + 21, bufIn + 1, 2); // random key part sent from remote client
			md5.Calculate(keyData, sizeof(keyData));
		} else if (currentTry == 2) {
			// kad packet with ReceiverKey as key
			kad = true;
			if (Kademlia::CKademlia::GetPrefs()) {
				uint8_t keyData[6];
				PokeUInt32(keyData, Kademlia::CPrefs::GetUDPVerifyKey(ip));
				memcpy(keyData + 4, bufIn + 1, 2); // random key part sent from remote client
				md5.Calculate(keyData, sizeof(keyData));
			}
		} else {
			wxFAIL;
		}

		receivebuffer.SetKey(md5, true);
		receivebuffer.RC4Crypt(bufIn + 3, (uint8_t*)&value, sizeof(value));
		ENDIAN_SWAP_I_32(value);

		currentTry = (currentTry + 1) % 3;
	} while (value != MAGICVALUE_UDP_SYNC_CLIENT && tries > 0); // try to decrypt as ed2k as well as kad packet if needed (max 3 rounds)

	if (value == MAGICVALUE_UDP_SYNC_CLIENT) {
		// yup this is an encrypted packet
//		// debugoutput notices
//		// the following cases are "allowed" but shouldn't happen given that there is only our implementation yet
//		if (bKad && (pbyBufIn[0] & 0x01) != 0)
//			DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, ed2k bit)"), ipstr(dwIP));
//		else if (bKad && !bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) != 0)
//			DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, nodeid key, recvkey bit)"), ipstr(dwIP));
//		else if (bKad && bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) == 0)
//			DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, recvkey key, nodeid bit)"), ipstr(dwIP));

		uint8_t padLen;
		receivebuffer.RC4Crypt(bufIn + 7, (uint8_t*)&padLen, 1);
		result -= CRYPT_HEADER_WITHOUTPADDING;

		if (result <= padLen) {
			//DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen);
			return bufLen; // pass through, let the Receivefunction do the errorhandling on this junk
		}

		if (padLen > 0) {
			receivebuffer.RC4Crypt(NULL, NULL, padLen);
		}

		result -= padLen;

		if (kad) {
			if (result <= 8) {
				//DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP));
				return bufLen; // pass through, let the Receivefunction do the errorhandling on this junk;
			}
			// read the verify keys
			receivebuffer.RC4Crypt(bufIn + CRYPT_HEADER_WITHOUTPADDING + padLen, (uint8_t*)receiverVerifyKey, 4);
			receivebuffer.RC4Crypt(bufIn + CRYPT_HEADER_WITHOUTPADDING + padLen + 4, (uint8_t*)senderVerifyKey, 4);
			ENDIAN_SWAP_I_32(*receiverVerifyKey);
			ENDIAN_SWAP_I_32(*senderVerifyKey);
			result -= 8;
		}

		*bufOut = bufIn + (bufLen - result);

		receivebuffer.RC4Crypt((uint8_t*)*bufOut, (uint8_t*)*bufOut, result);
		theStats::AddDownOverheadCrypt(bufLen - result);
		return result; // done
	} else {
		//DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP));
		return bufLen; // pass through, let the Receivefunction do the errorhandling on this junk
	}
}
int CEncryptedDatagramSocket::EncryptSendClient(uchar** ppbyBuf, int nBufLen, const uchar* pachClientHashOrKadID, bool bKad, uint16 nReceiverVerifyKey, uint16 nSenderVerifyKey) const{
	ASSERT( theApp.GetPublicIP() != 0 || bKad );
	ASSERT( thePrefs.IsClientCryptLayerSupported() );

	uint8 byPadLen = 0;			// padding disabled for UDP currently
	const uint32 nCryptHeaderLen = byPadLen + CRYPT_HEADER_WITHOUTPADDING + (bKad ? 4 : 0);
	uint32 nCryptedLen = nBufLen + nCryptHeaderLen;
	uchar* pachCryptedBuffer = new uchar[nCryptedLen];
	
	uint16 nRandomKeyPart = (uint16)cryptRandomGen.GenerateWord32(0x0000, 0xFFFF);
	MD5Sum md5;
	if (bKad){
		uchar achKeyData[18];
		md4cpy(achKeyData, pachClientHashOrKadID);
		memcpy(achKeyData+16, &nRandomKeyPart, 2);
		md5.Calculate(achKeyData, sizeof(achKeyData));
	}
	else{
		uchar achKeyData[23];
		md4cpy(achKeyData, pachClientHashOrKadID);
		uint32 dwIP = theApp.GetPublicIP();
		memcpy(achKeyData+16, &dwIP, 4);
		memcpy(achKeyData+21, &nRandomKeyPart, 2);
		achKeyData[20] = MAGICVALUE_UDP;
		md5.Calculate(achKeyData, sizeof(achKeyData));
	}
	RC4_Key_Struct keySendKey;
	RC4CreateKey(md5.GetRawHash(), 16, &keySendKey, true);

	// create the semi random byte encryption header
	uint8 bySemiRandomNotProtocolMarker = 0;
	int i;
	for (i = 0; i < 128; i++){
		bySemiRandomNotProtocolMarker = cryptRandomGen.GenerateByte();
		bySemiRandomNotProtocolMarker = bKad ? (bySemiRandomNotProtocolMarker & 0xFE) : (bySemiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit

		bool bOk = false;
		switch (bySemiRandomNotProtocolMarker){ // not allowed values
			case OP_EMULEPROT:
			case OP_KADEMLIAPACKEDPROT:
			case OP_KADEMLIAHEADER:
			case OP_UDPRESERVEDPROT1:
			case OP_UDPRESERVEDPROT2:
			case OP_PACKEDPROT:
				break;
			default:
				bOk = true;
		}
		if (bOk)
			break;
	}
	if (i >= 128){
		// either we have _real_ bad luck or the randomgenerator is a bit messed up
		ASSERT( false );
		bySemiRandomNotProtocolMarker = 0x01;
	}

	uint32 dwMagicValue = MAGICVALUE_UDP_SYNC_CLIENT;
	pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker;
	memcpy(pachCryptedBuffer + 1, &nRandomKeyPart, 2);
	RC4Crypt((uchar*)&dwMagicValue, pachCryptedBuffer + 3, 4, &keySendKey);
	RC4Crypt((uchar*)&byPadLen, pachCryptedBuffer + 7, 1, &keySendKey);

	for (int j = 0; j < byPadLen; j++){
		uint8 byRand = (uint8)rand();	// they actually dont really need to be random, but it doesn't hurts either
		RC4Crypt((uchar*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1, &keySendKey);
	}

	if (bKad){
		RC4Crypt((uchar*)&nReceiverVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, 2, &keySendKey);
		RC4Crypt((uchar*)&nSenderVerifyKey, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 2, 2, &keySendKey);
	}

	RC4Crypt(*ppbyBuf, pachCryptedBuffer + nCryptHeaderLen, nBufLen, &keySendKey);
	delete[] *ppbyBuf;
	*ppbyBuf = pachCryptedBuffer;

	theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);
	return nCryptedLen;
}
int CEncryptedDatagramSocket::DecryptReceivedClient(BYTE* pbyBufIn, int nBufLen, BYTE** ppbyBufOut, uint32 dwIP, uint16* nReceiverVerifyKey, uint16* nSenderVerifyKey) const{
	int nResult = nBufLen;
	*ppbyBufOut = pbyBufIn;
	
	if (nResult <= CRYPT_HEADER_WITHOUTPADDING /*|| !thePrefs.IsClientCryptLayerSupported()*/)
		return nResult;

	if (nReceiverVerifyKey == NULL || nSenderVerifyKey == NULL){
		ASSERT( false );
		return nResult;
	}
	
	switch (pbyBufIn[0]){
		case OP_EMULEPROT:
		case OP_KADEMLIAPACKEDPROT:
		case OP_KADEMLIAHEADER:
		case OP_UDPRESERVEDPROT1:
		case OP_UDPRESERVEDPROT2:
		case OP_PACKEDPROT:
			return nResult; // no encrypted packet (see description on top)
	}
	bool bKad = (pbyBufIn[0] & 0x01) == 0; // check the marker bit if this is a kad or ed2k packet, this is only an indicator since old clients have it set random
	// might be an encrypted packet, try to decrypt
	
	RC4_Key_Struct keyReceiveKey;
	uint32 dwValue = 0;
	bool bFlipTry = false;
	do{
		bKad = bFlipTry ? !bKad : bKad;
		MD5Sum md5;
		if (bKad){
			if (Kademlia::CKademlia::GetPrefs()) {
				uchar achKeyData[18];
				memcpy(achKeyData, Kademlia::CKademlia::GetPrefs()->GetKadID().GetData(), 16);
				memcpy(achKeyData + 16, pbyBufIn + 1, 2); // random key part sent from remote client
				md5.Calculate(achKeyData, sizeof(achKeyData));
			}
		}
		else{
			uchar achKeyData[23];
			md4cpy(achKeyData, thePrefs.GetUserHash());
			achKeyData[20] = MAGICVALUE_UDP;
			memcpy(achKeyData + 16, &dwIP, 4);
			memcpy(achKeyData + 21, pbyBufIn + 1, 2); // random key part sent from remote client
			md5.Calculate(achKeyData, sizeof(achKeyData));
		}
		RC4CreateKey(md5.GetRawHash(), 16, &keyReceiveKey, true);
		RC4Crypt(pbyBufIn + 3, (uchar*)&dwValue, sizeof(dwValue), &keyReceiveKey);
		bFlipTry = !bFlipTry; // next round try the other possibility
	} while (dwValue != MAGICVALUE_UDP_SYNC_CLIENT && bFlipTry); // try to decrypt as ed2k as well as kad packet if needed (max 2 rounds)
	
	if (dwValue == MAGICVALUE_UDP_SYNC_CLIENT){
		// yup this is an encrypted packet
		DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s"), ipstr(dwIP)) );
		uint8 byPadLen;
		RC4Crypt(pbyBufIn + 7, (uchar*)&byPadLen, 1, &keyReceiveKey);
		nResult -= CRYPT_HEADER_WITHOUTPADDING;
		if (nResult <= byPadLen){
			DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen);
			return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk
		}
		if (byPadLen > 0)
			RC4Crypt(NULL, NULL, byPadLen, &keyReceiveKey);
		nResult -= byPadLen;

		if (bKad){
			if (nResult <= 4){
				DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP));
				return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk;
			}
			// read the verify keys
			*nReceiverVerifyKey = PeekUInt16(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen);
			*nSenderVerifyKey = PeekUInt16(pbyBufIn + CRYPT_HEADER_WITHOUTPADDING + byPadLen + 2);
			nResult -= 4;
		}
		else{
			*nReceiverVerifyKey = 0;
			*nSenderVerifyKey = 0;
		}
		*ppbyBufOut = pbyBufIn + (nBufLen - nResult);
		RC4Crypt((uchar*)*ppbyBufOut, (uchar*)*ppbyBufOut, nResult, &keyReceiveKey);
		theStats.AddDownDataOverheadCrypt(nBufLen - nResult);
		return nResult; // done
	}
	else{
		DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP));
		return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk
	}
}