1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 6// 7// Any parts of this program derived from the xMule, lMule or eMule project, 8// or contributed by third-party developers are copyrighted by their 9// respective authors. 10// 11// This program is free software; you can redistribute it and/or modify 12// it under the terms of the GNU General Public License as published by 13// the Free Software Foundation; either version 2 of the License, or 14// (at your option) any later version. 15// 16// This program is distributed in the hope that it will be useful, 17// but WITHOUT ANY WARRANTY; without even the implied warranty of 18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19// GNU General Public License for more details. 20// 21// You should have received a copy of the GNU General Public License 22// along with this program; if not, write to the Free Software 23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 24// 25 26/* Basic Obfuscated Handshake Protocol UDP: 27 see EncryptedStreamSocket.h 28 29****************************** ED2K Packets 30 31- Keycreation Client <-> Client: 32 - Client A (Outgoing connection): 33 Sendkey: Md5(<UserHashClientB 16><IPClientA 4><MagicValue91 1><RandomKeyPartClientA 2>) 23 34 - Client B (Incoming connection): 35 Receivekey: Md5(<UserHashClientB 16><IPClientA 4><MagicValue91 1><RandomKeyPartClientA 2>) 23 36 - Note: The first 1024 Bytes will be _NOT_ discarded for UDP keys to save CPU time 37 38 - Handshake 39 -> The handshake is encrypted - except otherwise noted - by the Keys created above 40 -> Padding is currently not used for UDP meaning that PaddingLen will be 0, using PaddingLens up to 16 Bytes is acceptable however 41 Client A: <SemiRandomNotProtocolMarker 7 Bits[Unencrypted]><ED2K Marker 1Bit = 1><RandomKeyPart 2[Unencrypted]><MagicValue 4><PaddingLen 1><RandomBytes PaddingLen%16> 42 43 - Additional Comments: 44 - For obvious reasons the UDP handshake is actually no handshake. If a different Encryption method (or better a different Key) is to be used this has to be negotiated in a TCP connection 45 - SemiRandomNotProtocolMarker is a Byte which has a value unequal any Protocol header byte. This is a compromise, turning in complete randomness (and nice design) but gaining a lower CPU usage 46 - Kad/Ed2k Marker are only indicators, which possibility could be tried first, and should not be trusted 47 48****************************** Server Packets 49 50- Keycreation Client <-> Server: 51 - Client A (Outgoing connection client -> server): 52 Sendkey: Md5(<BaseKey 4><MagicValueClientServer 1><RandomKeyPartClientA 2>) 7 53 - Client B (Incoming connection): 54 Receivekey: Md5(<BaseKey 4><MagicValueServerClient 1><RandomKeyPartClientA 2>) 7 55 - Note: The first 1024 Bytes will be _NOT_ discarded for UDP keys to save CPU time 56 57 - Handshake 58 -> The handshake is encrypted - except otherwise noted - by the Keys created above 59 -> Padding is currently not used for UDP meaning that PaddingLen will be 0, using PaddingLens up to 16 Bytes is acceptable however 60 Client A: <SemiRandomNotProtocolMarker 1[Unencrypted]><RandomKeyPart 2[Unencrypted]><MagicValue 4><PaddingLen 1><RandomBytes PaddingLen%16> 61 62 - Overhead: 8 Bytes per UDP Packet 63 64 - Security for Basic Obfuscation: 65 - Random looking packets, very limited protection against passive eavesdropping single packets 66 67 - Additional Comments: 68 - For obvious reasons the UDP handshake is actually no handshake. If a different Encryption method (or better a different Key) is to be used this has to be negotiated in a TCP connection 69 - SemiRandomNotProtocolMarker is a Byte which has a value unequal any Protocol header byte. This is a compromise, turning in complete randomness (and nice design) but gaining a lower CPU usage 70 71****************************** KAD Packets 72 73- Keycreation Client <-> Client: 74 - Client A (Outgoing connection): 75 Sendkey: Md5(<KadID 16><RandomKeyPartClientA 2>) 18 76 - Client B (Incoming connection): 77 Receivekey: Md5(<KadID 16><RandomKeyPartClientA 2>) 18 78 - Note: The first 1024 Bytes will be _NOT_ discarded for UDP keys to save CPU time 79 80 - Handshake 81 -> The handshake is encrypted - except otherwise noted - by the Keys created above 82 -> Padding is currently not used for UDP meaning that PaddingLen will be 0, using PaddingLens up to 16 Bytes is acceptable however 83 Client A: <SemiRandomNotProtocolMarker 7 Bits[Unencrypted]><Kad Marker 1Bit = 0><RandomKeyPart 2[Unencrypted]><MagicValue 4><PaddingLen 1><RandomBytes PaddingLen%16><ReceiverVerifyKey 2><SenderVerifyKey 2> 84 85 - Overhead: 12 Bytes per UDP Packet 86 87 - Additional Comments: 88 - For obvious reasons the UDP handshake is actually no handshake. If a different Encryption method (or better a different Key) is to be used this has to be negotiated in a TCP connection 89 - SemiRandomNotProtocolMarker is a Byte which has a value unequal any Protocol header byte. This is a compromise, turning in complete randomness (and nice design) but gaining a lower CPU usage 90 - Kad/Ed2k Marker are only indicators, which possibility could be tried first, and should not be trusted 91*/ 92 93#include "EncryptedDatagramSocket.h" 94#include "amule.h" 95#include "Logger.h" 96#include "Preferences.h" 97#include "RC4Encrypt.h" 98#include "./kademlia/kademlia/Prefs.h" 99#include "./kademlia/kademlia/Kademlia.h" 100#include "RandomFunctions.h" 101#include "Statistics.h" 102 103#include <protocol/Protocols.h> 104#include <common/MD5Sum.h> 105 106// random generator 107#include "CryptoPP_Inc.h" // Needed for Crypto functions 108 109#define CRYPT_HEADER_WITHOUTPADDING 8 110#define MAGICVALUE_UDP 91 111#define MAGICVALUE_UDP_SYNC_CLIENT 0x395F2EC1 112#define MAGICVALUE_UDP_SYNC_SERVER 0x13EF24D5 113#define MAGICVALUE_UDP_SERVERCLIENT 0xA5 114#define MAGICVALUE_UDP_CLIENTSERVER 0x6B 115 116CEncryptedDatagramSocket::CEncryptedDatagramSocket(wxIPaddress &address, wxSocketFlags flags, const CProxyData *proxyData) 117 : CDatagramSocketProxy(address, flags, proxyData) 118{} 119 120CEncryptedDatagramSocket::~CEncryptedDatagramSocket() 121{} 122 123int CEncryptedDatagramSocket::DecryptReceivedClient(uint8_t *bufIn, int bufLen, uint8_t **bufOut, uint32_t ip, uint32_t *receiverVerifyKey, uint32_t *senderVerifyKey) 124{ 125 int result = bufLen; 126 *bufOut = bufIn; 127 128 if (receiverVerifyKey == NULL || senderVerifyKey == NULL) { 129 wxFAIL; 130 return result; 131 } 132 133 *receiverVerifyKey = 0; 134 *senderVerifyKey = 0; 135 136 if (result <= CRYPT_HEADER_WITHOUTPADDING /*|| !thePrefs.IsClientCryptLayerSupported()*/) { 137 return result; 138 } 139 140 switch (bufIn[0]) { 141 case OP_EMULEPROT: 142 case OP_KADEMLIAPACKEDPROT: 143 case OP_KADEMLIAHEADER: 144 case OP_UDPRESERVEDPROT1: 145 case OP_UDPRESERVEDPROT2: 146 case OP_PACKEDPROT: 147 return result; // no encrypted packet (see description on top) 148 default: 149 ; 150 } 151 152 // might be an encrypted packet, try to decrypt 153 CRC4EncryptableBuffer receivebuffer; 154 uint32_t value = 0; 155 // 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 156 // see the header for marker bits explanation 157 uint8_t currentTry = ((bufIn[0] & 0x03) == 3) ? 1 : (bufIn[0] & 0x03); 158 uint8_t tries; 159 if (Kademlia::CKademlia::GetPrefs() == NULL) { 160 // if kad never run, no point in checking anything except for ed2k encryption 161 tries = 1; 162 currentTry = 1; 163 } else { 164 tries = 3; 165 } 166 bool kad = false; 167 do { 168 receivebuffer.FullReset(); 169 tries--; 170 MD5Sum md5; 171 172 if (currentTry == 0) { 173 // kad packet with NodeID as key 174 kad = true; 175 if (Kademlia::CKademlia::GetPrefs()) { 176 uint8_t keyData[18]; 177 Kademlia::CKademlia::GetPrefs()->GetKadID().StoreCryptValue((uint8_t *)&keyData); 178 memcpy(keyData + 16, bufIn + 1, 2); // random key part sent from remote client 179 md5.Calculate(keyData, sizeof(keyData)); 180 } 181 } else if (currentTry == 1) { 182 // ed2k packet 183 kad = false; 184 uint8_t keyData[23]; 185 md4cpy(keyData, thePrefs::GetUserHash().GetHash()); 186 keyData[20] = MAGICVALUE_UDP; 187 PokeUInt32(keyData + 16, ip); 188 memcpy(keyData + 21, bufIn + 1, 2); // random key part sent from remote client 189 md5.Calculate(keyData, sizeof(keyData)); 190 } else if (currentTry == 2) { 191 // kad packet with ReceiverKey as key 192 kad = true; 193 if (Kademlia::CKademlia::GetPrefs()) { 194 uint8_t keyData[6]; 195 PokeUInt32(keyData, Kademlia::CPrefs::GetUDPVerifyKey(ip)); 196 memcpy(keyData + 4, bufIn + 1, 2); // random key part sent from remote client 197 md5.Calculate(keyData, sizeof(keyData)); 198 } 199 } else { 200 wxFAIL; 201 } 202 203 receivebuffer.SetKey(md5, true); 204 receivebuffer.RC4Crypt(bufIn + 3, (uint8_t*)&value, sizeof(value)); 205 ENDIAN_SWAP_I_32(value); 206 207 currentTry = (currentTry + 1) % 3; 208 } while (value != MAGICVALUE_UDP_SYNC_CLIENT && tries > 0); // try to decrypt as ed2k as well as kad packet if needed (max 3 rounds) 209 210 if (value == MAGICVALUE_UDP_SYNC_CLIENT) { 211 // yup this is an encrypted packet 212// // debugoutput notices 213// // the following cases are "allowed" but shouldn't happen given that there is only our implementation yet 214// if (bKad && (pbyBufIn[0] & 0x01) != 0) 215// DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, ed2k bit)"), ipstr(dwIP)); 216// else if (bKad && !bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) != 0) 217// DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, nodeid key, recvkey bit)"), ipstr(dwIP)); 218// else if (bKad && bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) == 0) 219// DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, recvkey key, nodeid bit)"), ipstr(dwIP)); 220 221 uint8_t padLen; 222 receivebuffer.RC4Crypt(bufIn + 7, (uint8_t*)&padLen, 1); 223 result -= CRYPT_HEADER_WITHOUTPADDING; 224 225 if (result <= padLen) { 226 //DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen); 227 return bufLen; // pass through, let the Receivefunction do the errorhandling on this junk 228 } 229 230 if (padLen > 0) { 231 receivebuffer.RC4Crypt(NULL, NULL, padLen); 232 } 233 234 result -= padLen; 235 236 if (kad) { 237 if (result <= 8) { 238 //DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP)); 239 return bufLen; // pass through, let the Receivefunction do the errorhandling on this junk; 240 } 241 // read the verify keys 242 receivebuffer.RC4Crypt(bufIn + CRYPT_HEADER_WITHOUTPADDING + padLen, (uint8_t*)receiverVerifyKey, 4); 243 receivebuffer.RC4Crypt(bufIn + CRYPT_HEADER_WITHOUTPADDING + padLen + 4, (uint8_t*)senderVerifyKey, 4); 244 ENDIAN_SWAP_I_32(*receiverVerifyKey); 245 ENDIAN_SWAP_I_32(*senderVerifyKey); 246 result -= 8; 247 } 248 249 *bufOut = bufIn + (bufLen - result); 250 251 receivebuffer.RC4Crypt((uint8_t*)*bufOut, (uint8_t*)*bufOut, result); 252 theStats::AddDownOverheadCrypt(bufLen - result); 253 return result; // done 254 } else { 255 //DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP)); 256 return bufLen; // pass through, let the Receivefunction do the errorhandling on this junk 257 } 258} 259 260// Encrypt packet. Key used: 261// clientHashOrKadID != NULL -> clientHashOrKadID 262// clientHashOrKadID == NULL && kad && receiverVerifyKey != 0 -> receiverVerifyKey 263// else -> ASSERT 264int CEncryptedDatagramSocket::EncryptSendClient(uint8_t **buf, int bufLen, const uint8_t *clientHashOrKadID, bool kad, uint32_t receiverVerifyKey, uint32_t senderVerifyKey) 265{ 266 wxASSERT(theApp->GetPublicIP() != 0 || kad); 267 wxASSERT(thePrefs::IsClientCryptLayerSupported()); 268 wxASSERT(clientHashOrKadID != NULL || receiverVerifyKey != 0); 269 wxASSERT((receiverVerifyKey == 0 && senderVerifyKey == 0) || kad); 270 271 uint8_t padLen = 0; // padding disabled for UDP currently 272 const uint32_t cryptHeaderLen = padLen + CRYPT_HEADER_WITHOUTPADDING + (kad ? 8 : 0); 273 uint32_t cryptedLen = bufLen + cryptHeaderLen; 274 uint8_t *cryptedBuffer = new uint8_t[cryptedLen]; 275 bool kadRecvKeyUsed = false; 276 277 uint16_t randomKeyPart = GetRandomUint16(); 278 CRC4EncryptableBuffer sendbuffer; 279 MD5Sum md5; 280 if (kad) { 281 if ((clientHashOrKadID == NULL || CMD4Hash(clientHashOrKadID).IsEmpty()) && receiverVerifyKey != 0) { 282 kadRecvKeyUsed = true; 283 uint8_t keyData[6]; 284 PokeUInt32(keyData, receiverVerifyKey); 285 PokeUInt16(keyData+4, randomKeyPart); 286 md5.Calculate(keyData, sizeof(keyData)); 287 //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) ); 288 } 289 else if (clientHashOrKadID != NULL && !CMD4Hash(clientHashOrKadID).IsEmpty()) { 290 uint8_t keyData[18]; 291 md4cpy(keyData, clientHashOrKadID); 292 PokeUInt16(keyData+16, randomKeyPart); 293 md5.Calculate(keyData, sizeof(keyData)); 294 //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) ); 295 } 296 else { 297 wxFAIL; 298 return bufLen; 299 } 300 } else { 301 uint8_t keyData[23]; 302 md4cpy(keyData, clientHashOrKadID); 303 PokeUInt32(keyData+16, theApp->GetPublicIP()); 304 PokeUInt16(keyData+21, randomKeyPart); 305 keyData[20] = MAGICVALUE_UDP; 306 md5.Calculate(keyData, sizeof(keyData)); 307 } 308 309 sendbuffer.SetKey(md5, true); 310 311 // create the semi random byte encryption header 312 uint8_t semiRandomNotProtocolMarker = 0; 313 int i; 314 for (i = 0; i < 128; i++) { 315 semiRandomNotProtocolMarker = GetRandomUint8(); 316 semiRandomNotProtocolMarker = kad ? (semiRandomNotProtocolMarker & 0xFE) : (semiRandomNotProtocolMarker | 0x01); // set the ed2k/kad marker bit 317 if (kad) { 318 // set the ed2k/kad and nodeid/recvkey markerbit 319 semiRandomNotProtocolMarker = kadRecvKeyUsed ? ((semiRandomNotProtocolMarker & 0xFE) | 0x02) : (semiRandomNotProtocolMarker & 0xFC); 320 } else { 321 // set the ed2k/kad marker bit 322 semiRandomNotProtocolMarker = (semiRandomNotProtocolMarker | 0x01); 323 } 324 325 bool bOk = false; 326 switch (semiRandomNotProtocolMarker) { // not allowed values 327 case OP_EMULEPROT: 328 case OP_KADEMLIAPACKEDPROT: 329 case OP_KADEMLIAHEADER: 330 case OP_UDPRESERVEDPROT1: 331 case OP_UDPRESERVEDPROT2: 332 case OP_PACKEDPROT: 333 break; 334 default: 335 bOk = true; 336 } 337 338 if (bOk) { 339 break; 340 } 341 } 342 343 if (i >= 128) { 344 // either we have _real_ bad luck or the randomgenerator is a bit messed up 345 wxFAIL; 346 semiRandomNotProtocolMarker = 0x01; 347 } 348 349 cryptedBuffer[0] = semiRandomNotProtocolMarker; 350 PokeUInt16(cryptedBuffer + 1, randomKeyPart); 351 352 uint32_t magicValue = ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_CLIENT); 353 sendbuffer.RC4Crypt((uint8_t*)&magicValue, cryptedBuffer + 3, 4); 354 sendbuffer.RC4Crypt((uint8_t*)&padLen, cryptedBuffer + 7, 1); 355 356 for (int j = 0; j < padLen; j++) { 357 uint8_t byRand = (uint8_t)rand(); // they actually don't really need to be random, but it doesn't hurt either 358 sendbuffer.RC4Crypt((uint8_t*)&byRand, cryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1); 359 } 360 361 if (kad) { 362 ENDIAN_SWAP_I_32(receiverVerifyKey); 363 ENDIAN_SWAP_I_32(senderVerifyKey); 364 sendbuffer.RC4Crypt((uint8_t*)&receiverVerifyKey, cryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + padLen, 4); 365 sendbuffer.RC4Crypt((uint8_t*)&senderVerifyKey, cryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + padLen + 4, 4); 366 } 367 368 sendbuffer.RC4Crypt(*buf, cryptedBuffer + cryptHeaderLen, bufLen); 369 delete [] *buf; 370 *buf = cryptedBuffer; 371 372 theStats::AddUpOverheadCrypt(cryptedLen - bufLen); 373 return cryptedLen; 374} 375 376int CEncryptedDatagramSocket::DecryptReceivedServer(uint8_t* pbyBufIn, int nBufLen, uint8_t **ppbyBufOut, uint32_t dwBaseKey, uint32_t /*dbgIP*/) 377{ 378 int nResult = nBufLen; 379 *ppbyBufOut = pbyBufIn; 380 381 if (nResult <= CRYPT_HEADER_WITHOUTPADDING || !thePrefs::IsServerCryptLayerUDPEnabled() || dwBaseKey == 0) { 382 return nResult; 383 } 384 385 if(pbyBufIn[0] == OP_EDONKEYPROT) { 386 return nResult; // no encrypted packet (see description on top) 387 } 388 389 // might be an encrypted packet, try to decrypt 390 uint8_t achKeyData[7]; 391 PokeUInt32(achKeyData, dwBaseKey); 392 achKeyData[4] = MAGICVALUE_UDP_SERVERCLIENT; 393 memcpy(achKeyData + 5, pbyBufIn + 1, 2); // random key part sent from remote server 394 395 CRC4EncryptableBuffer receivebuffer; 396 MD5Sum md5(achKeyData, sizeof(achKeyData)); 397 receivebuffer.SetKey(md5,true); 398 399 uint32_t dwValue; 400 receivebuffer.RC4Crypt(pbyBufIn + 3, (uint8_t*)&dwValue, sizeof(dwValue)); 401 ENDIAN_SWAP_I_32(dwValue); 402 if (dwValue == MAGICVALUE_UDP_SYNC_SERVER) { 403 // yup this is an encrypted packet 404 //DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from ServerIP: %s"), ipstr(dbgIP)) ); 405 uint8_t byPadLen; 406 receivebuffer.RC4Crypt(pbyBufIn + 7, (uint8_t*)&byPadLen, 1); 407 byPadLen &= 15; 408 nResult -= CRYPT_HEADER_WITHOUTPADDING; 409 410 if (nResult <= byPadLen) { 411 //DebugLogError(_T("Invalid obfuscated UDP packet from ServerIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dbgIP), byPadLen); 412 return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk 413 } 414 415 if (byPadLen > 0) { 416 receivebuffer.RC4Crypt(NULL, NULL, byPadLen); 417 } 418 419 nResult -= byPadLen; 420 *ppbyBufOut = pbyBufIn + (nBufLen - nResult); 421 receivebuffer.RC4Crypt((uint8_t*)*ppbyBufOut, (uint8_t*)*ppbyBufOut, nResult); 422 423 theStats::AddDownOverheadCrypt(nBufLen - nResult); 424 return nResult; // done 425 } else { 426 //DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from ServerIP: %s"), ipstr(dbgIP)); 427 return nBufLen; // pass through, let the Receivefunction do the errorhandling on this junk 428 } 429} 430 431int CEncryptedDatagramSocket::EncryptSendServer(uint8_t** ppbyBuf, int nBufLen, uint32_t dwBaseKey) 432{ 433 wxASSERT( thePrefs::IsServerCryptLayerUDPEnabled() ); 434 wxASSERT( dwBaseKey != 0 ); 435 436 uint16_t nRandomKeyPart = GetRandomUint16(); 437 438 uint8_t achKeyData[7]; 439 PokeUInt32(achKeyData, dwBaseKey); 440 achKeyData[4] = MAGICVALUE_UDP_CLIENTSERVER; 441 PokeUInt16(achKeyData + 5, nRandomKeyPart); 442 MD5Sum md5(achKeyData, sizeof(achKeyData)); 443 CRC4EncryptableBuffer sendbuffer; 444 sendbuffer.SetKey(md5, true); 445 446 // create the semi random byte encryption header 447 uint8_t bySemiRandomNotProtocolMarker = 0; 448 int i; 449 450 for (i = 0; i < 128; i++) { 451 bySemiRandomNotProtocolMarker = GetRandomUint8(); 452 if (bySemiRandomNotProtocolMarker != OP_EDONKEYPROT) { // not allowed values 453 break; 454 } 455 } 456 457 if (i >= 128) { 458 // either we have _real_ bad luck or the randomgenerator is a bit messed up 459 wxFAIL; 460 bySemiRandomNotProtocolMarker = 0x01; 461 } 462 463 uint8_t byPadLen = 0; // padding disabled for UDP currently 464 uint32_t nCryptedLen = nBufLen + byPadLen + CRYPT_HEADER_WITHOUTPADDING; 465 uint8_t* pachCryptedBuffer = new uint8_t[nCryptedLen]; 466 467 pachCryptedBuffer[0] = bySemiRandomNotProtocolMarker; 468 PokeUInt16(pachCryptedBuffer + 1, nRandomKeyPart); 469 470 uint32_t dwMagicValue = ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_SERVER); 471 sendbuffer.RC4Crypt((uint8_t*)&dwMagicValue, pachCryptedBuffer + 3, 4); 472 473 sendbuffer.RC4Crypt((uint8_t*)&byPadLen, pachCryptedBuffer + 7, 1); 474 475 for (int j = 0; j < byPadLen; j++){ 476 uint8_t byRand = (uint8_t)rand(); // they actually don't really need to be random, but it doesn't hurt either 477 sendbuffer.RC4Crypt((uint8_t*)&byRand, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + j, 1); 478 } 479 sendbuffer.RC4Crypt(*ppbyBuf, pachCryptedBuffer + CRYPT_HEADER_WITHOUTPADDING + byPadLen, nBufLen); 480 delete[] *ppbyBuf; 481 *ppbyBuf = pachCryptedBuffer; 482 483 theStats::AddUpOverheadCrypt(nCryptedLen - nBufLen); 484 return nCryptedLen; 485} 486