2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 Merkur ( devs@emule-project.net / http://www.emule-project.net )
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
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.
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.
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
26 /* Basic Obfuscated Handshake Protocol UDP:
27 see EncryptedStreamSocket.h
29 ****************************** ED2K Packets
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
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>
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
48 ****************************** Server Packets
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
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>
62 - Overhead: 8 Bytes per UDP Packet
64 - Security for Basic Obfuscation:
65 - Random looking packets, very limited protection against passive eavesdropping single packets
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
71 ****************************** KAD Packets
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
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>
85 - Overhead: 12 Bytes per UDP Packet
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
93 #include "EncryptedDatagramSocket.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"
103 #include <protocol/Protocols.h>
104 #include <common/MD5Sum.h>
107 #include "CryptoPP_Inc.h" // Needed for Crypto functions
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
116 CEncryptedDatagramSocket::CEncryptedDatagramSocket(wxIPaddress
&address
, wxSocketFlags flags
, const CProxyData
*proxyData
)
117 : CDatagramSocketProxy(address
, flags
, proxyData
)
120 CEncryptedDatagramSocket::~CEncryptedDatagramSocket()
123 int CEncryptedDatagramSocket::DecryptReceivedClient(uint8_t *bufIn
, int bufLen
, uint8_t **bufOut
, uint32_t ip
, uint32_t *receiverVerifyKey
, uint32_t *senderVerifyKey
)
128 if (receiverVerifyKey
== NULL
|| senderVerifyKey
== NULL
) {
133 *receiverVerifyKey
= 0;
134 *senderVerifyKey
= 0;
136 if (result
<= CRYPT_HEADER_WITHOUTPADDING
/*|| !thePrefs.IsClientCryptLayerSupported()*/) {
142 case OP_KADEMLIAPACKEDPROT
:
143 case OP_KADEMLIAHEADER
:
144 case OP_UDPRESERVEDPROT1
:
145 case OP_UDPRESERVEDPROT2
:
147 return result
; // no encrypted packet (see description on top)
152 // might be an encrypted packet, try to decrypt
153 CRC4EncryptableBuffer receivebuffer
;
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);
159 if (Kademlia::CKademlia::GetPrefs() == NULL
) {
160 // if kad never run, no point in checking anything except for ed2k encryption
166 bool kadRecvKeyUsed
= false;
169 receivebuffer
.FullReset();
173 if (currentTry
== 0) {
174 // kad packet with NodeID as key
176 kadRecvKeyUsed
= false;
177 if (Kademlia::CKademlia::GetPrefs()) {
179 Kademlia::CKademlia::GetPrefs()->GetKadID().StoreCryptValue((uint8_t *)&keyData
);
180 memcpy(keyData
+ 16, bufIn
+ 1, 2); // random key part sent from remote client
181 md5
.Calculate(keyData
, sizeof(keyData
));
183 } else if (currentTry
== 1) {
186 kadRecvKeyUsed
= false;
188 md4cpy(keyData
, thePrefs::GetUserHash().GetHash());
189 keyData
[20] = MAGICVALUE_UDP
;
190 PokeUInt32(keyData
+ 16, ip
);
191 memcpy(keyData
+ 21, bufIn
+ 1, 2); // random key part sent from remote client
192 md5
.Calculate(keyData
, sizeof(keyData
));
193 } else if (currentTry
== 2) {
194 // kad packet with ReceiverKey as key
196 kadRecvKeyUsed
= true;
197 if (Kademlia::CKademlia::GetPrefs()) {
199 PokeUInt32(keyData
, Kademlia::CPrefs::GetUDPVerifyKey(ip
));
200 memcpy(keyData
+ 4, bufIn
+ 1, 2); // random key part sent from remote client
201 md5
.Calculate(keyData
, sizeof(keyData
));
207 receivebuffer
.SetKey(md5
, true);
208 receivebuffer
.RC4Crypt(bufIn
+ 3, (uint8_t*)&value
, sizeof(value
));
209 ENDIAN_SWAP_I_32(value
);
211 currentTry
= (currentTry
+ 1) % 3;
212 } while (value
!= MAGICVALUE_UDP_SYNC_CLIENT
&& tries
> 0); // try to decrypt as ed2k as well as kad packet if needed (max 3 rounds)
214 if (value
== MAGICVALUE_UDP_SYNC_CLIENT
) {
215 // yup this is an encrypted packet
216 // // debugoutput notices
217 // // the following cases are "allowed" but shouldn't happen given that there is only our implementation yet
218 // if (bKad && (pbyBufIn[0] & 0x01) != 0)
219 // DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, ed2k bit)"), ipstr(dwIP));
220 // else if (bKad && !bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) != 0)
221 // DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, nodeid key, recvkey bit)"), ipstr(dwIP));
222 // else if (bKad && bKadRecvKeyUsed && (pbyBufIn[0] & 0x02) == 0)
223 // DebugLog(_T("Received obfuscated UDP packet from clientIP: %s with wrong key marker bits (kad packet, recvkey key, nodeid bit)"), ipstr(dwIP));
226 receivebuffer
.RC4Crypt(bufIn
+ 7, (uint8_t*)&padLen
, 1);
227 result
-= CRYPT_HEADER_WITHOUTPADDING
;
229 if (result
<= padLen
) {
230 //DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen);
231 return bufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
235 receivebuffer
.RC4Crypt(NULL
, NULL
, padLen
);
242 //DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP));
243 return bufLen
; // pass through, let the Receivefunction do the errorhandling on this junk;
245 // read the verify keys
246 receivebuffer
.RC4Crypt(bufIn
+ CRYPT_HEADER_WITHOUTPADDING
+ padLen
, (uint8_t*)receiverVerifyKey
, 4);
247 receivebuffer
.RC4Crypt(bufIn
+ CRYPT_HEADER_WITHOUTPADDING
+ padLen
+ 4, (uint8_t*)senderVerifyKey
, 4);
248 ENDIAN_SWAP_I_32(*receiverVerifyKey
);
249 ENDIAN_SWAP_I_32(*senderVerifyKey
);
253 *bufOut
= bufIn
+ (bufLen
- result
);
255 receivebuffer
.RC4Crypt((uint8_t*)*bufOut
, (uint8_t*)*bufOut
, result
);
256 theStats::AddDownOverheadCrypt(bufLen
- result
);
257 return result
; // done
259 //DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP));
260 return bufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
264 // Encrypt packet. Key used:
265 // clientHashOrKadID != NULL -> clientHashOrKadID
266 // clientHashOrKadID == NULL && kad && receiverVerifyKey != 0 -> receiverVerifyKey
268 int CEncryptedDatagramSocket::EncryptSendClient(uint8_t **buf
, int bufLen
, const uint8_t *clientHashOrKadID
, bool kad
, uint32_t receiverVerifyKey
, uint32_t senderVerifyKey
)
270 wxASSERT(theApp
->GetPublicIP() != 0 || kad
);
271 wxASSERT(thePrefs::IsClientCryptLayerSupported());
272 wxASSERT(clientHashOrKadID
!= NULL
|| receiverVerifyKey
!= 0);
273 wxASSERT((receiverVerifyKey
== 0 && senderVerifyKey
== 0) || kad
);
275 uint8_t padLen
= 0; // padding disabled for UDP currently
276 const uint32_t cryptHeaderLen
= padLen
+ CRYPT_HEADER_WITHOUTPADDING
+ (kad
? 8 : 0);
277 uint32_t cryptedLen
= bufLen
+ cryptHeaderLen
;
278 uint8_t *cryptedBuffer
= new uint8_t[cryptedLen
];
279 bool kadRecvKeyUsed
= false;
281 uint16_t randomKeyPart
= GetRandomUint16();
282 CRC4EncryptableBuffer sendbuffer
;
285 if ((clientHashOrKadID
== NULL
|| CMD4Hash(clientHashOrKadID
).IsEmpty()) && receiverVerifyKey
!= 0) {
286 kadRecvKeyUsed
= true;
288 PokeUInt32(keyData
, receiverVerifyKey
);
289 PokeUInt16(keyData
+4, randomKeyPart
);
290 md5
.Calculate(keyData
, sizeof(keyData
));
291 //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by ReceiverKey (%u)"), nReceiverVerifyKey) );
293 else if (clientHashOrKadID
!= NULL
&& !CMD4Hash(clientHashOrKadID
).IsEmpty()) {
295 md4cpy(keyData
, clientHashOrKadID
);
296 PokeUInt16(keyData
+16, randomKeyPart
);
297 md5
.Calculate(keyData
, sizeof(keyData
));
298 //DEBUG_ONLY( DebugLog(_T("Creating obfuscated Kad packet encrypted by Hash/NodeID %s"), md4str(pachClientHashOrKadID)) );
306 md4cpy(keyData
, clientHashOrKadID
);
307 PokeUInt32(keyData
+16, theApp
->GetPublicIP());
308 PokeUInt16(keyData
+21, randomKeyPart
);
309 keyData
[20] = MAGICVALUE_UDP
;
310 md5
.Calculate(keyData
, sizeof(keyData
));
313 sendbuffer
.SetKey(md5
, true);
315 // create the semi random byte encryption header
316 uint8_t semiRandomNotProtocolMarker
= 0;
318 for (i
= 0; i
< 128; i
++) {
319 semiRandomNotProtocolMarker
= GetRandomUint8();
320 semiRandomNotProtocolMarker
= kad
? (semiRandomNotProtocolMarker
& 0xFE) : (semiRandomNotProtocolMarker
| 0x01); // set the ed2k/kad marker bit
322 // set the ed2k/kad and nodeid/recvkey markerbit
323 semiRandomNotProtocolMarker
= kadRecvKeyUsed
? ((semiRandomNotProtocolMarker
& 0xFE) | 0x02) : (semiRandomNotProtocolMarker
& 0xFC);
325 // set the ed2k/kad marker bit
326 semiRandomNotProtocolMarker
= (semiRandomNotProtocolMarker
| 0x01);
330 switch (semiRandomNotProtocolMarker
) { // not allowed values
332 case OP_KADEMLIAPACKEDPROT
:
333 case OP_KADEMLIAHEADER
:
334 case OP_UDPRESERVEDPROT1
:
335 case OP_UDPRESERVEDPROT2
:
348 // either we have _real_ bad luck or the randomgenerator is a bit messed up
350 semiRandomNotProtocolMarker
= 0x01;
353 cryptedBuffer
[0] = semiRandomNotProtocolMarker
;
354 PokeUInt16(cryptedBuffer
+ 1, randomKeyPart
);
356 uint32_t magicValue
= ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_CLIENT
);
357 sendbuffer
.RC4Crypt((uint8_t*)&magicValue
, cryptedBuffer
+ 3, 4);
358 sendbuffer
.RC4Crypt((uint8_t*)&padLen
, cryptedBuffer
+ 7, 1);
360 for (int j
= 0; j
< padLen
; j
++) {
361 uint8_t byRand
= (uint8_t)rand(); // they actually don't really need to be random, but it doesn't hurt either
362 sendbuffer
.RC4Crypt((uint8_t*)&byRand
, cryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ j
, 1);
366 ENDIAN_SWAP_I_32(receiverVerifyKey
);
367 ENDIAN_SWAP_I_32(senderVerifyKey
);
368 sendbuffer
.RC4Crypt((uint8_t*)&receiverVerifyKey
, cryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ padLen
, 4);
369 sendbuffer
.RC4Crypt((uint8_t*)&senderVerifyKey
, cryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ padLen
+ 4, 4);
372 sendbuffer
.RC4Crypt(*buf
, cryptedBuffer
+ cryptHeaderLen
, bufLen
);
374 *buf
= cryptedBuffer
;
376 theStats::AddUpOverheadCrypt(cryptedLen
- bufLen
);
380 int CEncryptedDatagramSocket::DecryptReceivedServer(uint8_t* pbyBufIn
, int nBufLen
, uint8_t **ppbyBufOut
, uint32_t dwBaseKey
, uint32_t /*dbgIP*/)
382 int nResult
= nBufLen
;
383 *ppbyBufOut
= pbyBufIn
;
385 if (nResult
<= CRYPT_HEADER_WITHOUTPADDING
|| !thePrefs::IsServerCryptLayerUDPEnabled() || dwBaseKey
== 0) {
389 if(pbyBufIn
[0] == OP_EDONKEYPROT
) {
390 return nResult
; // no encrypted packet (see description on top)
393 // might be an encrypted packet, try to decrypt
394 uint8_t achKeyData
[7];
395 PokeUInt32(achKeyData
, dwBaseKey
);
396 achKeyData
[4] = MAGICVALUE_UDP_SERVERCLIENT
;
397 memcpy(achKeyData
+ 5, pbyBufIn
+ 1, 2); // random key part sent from remote server
399 CRC4EncryptableBuffer receivebuffer
;
400 MD5Sum
md5(achKeyData
, sizeof(achKeyData
));
401 receivebuffer
.SetKey(md5
,true);
404 receivebuffer
.RC4Crypt(pbyBufIn
+ 3, (uint8_t*)&dwValue
, sizeof(dwValue
));
405 ENDIAN_SWAP_I_32(dwValue
);
406 if (dwValue
== MAGICVALUE_UDP_SYNC_SERVER
) {
407 // yup this is an encrypted packet
408 //DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from ServerIP: %s"), ipstr(dbgIP)) );
410 receivebuffer
.RC4Crypt(pbyBufIn
+ 7, (uint8_t*)&byPadLen
, 1);
412 nResult
-= CRYPT_HEADER_WITHOUTPADDING
;
414 if (nResult
<= byPadLen
) {
415 //DebugLogError(_T("Invalid obfuscated UDP packet from ServerIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dbgIP), byPadLen);
416 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
420 receivebuffer
.RC4Crypt(NULL
, NULL
, byPadLen
);
424 *ppbyBufOut
= pbyBufIn
+ (nBufLen
- nResult
);
425 receivebuffer
.RC4Crypt((uint8_t*)*ppbyBufOut
, (uint8_t*)*ppbyBufOut
, nResult
);
427 theStats::AddDownOverheadCrypt(nBufLen
- nResult
);
428 return nResult
; // done
430 //DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from ServerIP: %s"), ipstr(dbgIP));
431 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
435 int CEncryptedDatagramSocket::EncryptSendServer(uint8_t** ppbyBuf
, int nBufLen
, uint32_t dwBaseKey
)
437 wxASSERT( thePrefs::IsServerCryptLayerUDPEnabled() );
438 wxASSERT( dwBaseKey
!= 0 );
440 uint16_t nRandomKeyPart
= GetRandomUint16();
442 uint8_t achKeyData
[7];
443 PokeUInt32(achKeyData
, dwBaseKey
);
444 achKeyData
[4] = MAGICVALUE_UDP_CLIENTSERVER
;
445 PokeUInt16(achKeyData
+ 5, nRandomKeyPart
);
446 MD5Sum
md5(achKeyData
, sizeof(achKeyData
));
447 CRC4EncryptableBuffer sendbuffer
;
448 sendbuffer
.SetKey(md5
, true);
450 // create the semi random byte encryption header
451 uint8_t bySemiRandomNotProtocolMarker
= 0;
454 for (i
= 0; i
< 128; i
++) {
455 bySemiRandomNotProtocolMarker
= GetRandomUint8();
456 if (bySemiRandomNotProtocolMarker
!= OP_EDONKEYPROT
) { // not allowed values
462 // either we have _real_ bad luck or the randomgenerator is a bit messed up
464 bySemiRandomNotProtocolMarker
= 0x01;
467 uint8_t byPadLen
= 0; // padding disabled for UDP currently
468 uint32_t nCryptedLen
= nBufLen
+ byPadLen
+ CRYPT_HEADER_WITHOUTPADDING
;
469 uint8_t* pachCryptedBuffer
= new uint8_t[nCryptedLen
];
471 pachCryptedBuffer
[0] = bySemiRandomNotProtocolMarker
;
472 PokeUInt16(pachCryptedBuffer
+ 1, nRandomKeyPart
);
474 uint32_t dwMagicValue
= ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_SERVER
);
475 sendbuffer
.RC4Crypt((uint8_t*)&dwMagicValue
, pachCryptedBuffer
+ 3, 4);
477 sendbuffer
.RC4Crypt((uint8_t*)&byPadLen
, pachCryptedBuffer
+ 7, 1);
479 for (int j
= 0; j
< byPadLen
; j
++){
480 uint8_t byRand
= (uint8_t)rand(); // they actually don't really need to be random, but it doesn't hurt either
481 sendbuffer
.RC4Crypt((uint8_t*)&byRand
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ j
, 1);
483 sendbuffer
.RC4Crypt(*ppbyBuf
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ byPadLen
, nBufLen
);
485 *ppbyBuf
= pachCryptedBuffer
;
487 theStats::AddUpOverheadCrypt(nCryptedLen
- nBufLen
);