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); } }
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); }
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; } }
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); }
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; }
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); }
CDeadSource::CDeadSource(const uchar* paucHash){ m_dwID = 0; m_dwServerIP = 0; m_nPort = 0; m_nKadPort = 0; md4cpy(m_aucHash, paucHash); }
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; }
//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); }
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 } }
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; }
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); }
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)); }
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()); }
//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; }
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); }
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; } }
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; } }
// 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; }
void CAbstractFile::SetFileHash(const uchar* pucFileHash) { md4cpy(m_abyFileHash, pucFileHash); }
//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 } }
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 } }