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 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 Obfusicated Handshake Protocol UDP:
27 see EncryptedStreamSocket.h
29 ****************************** ED2K Packets
31 -Keycreation Client <-> Clinet:
32 - Client A (Outgoing connection):
33 Sendkey: Md5(<UserHashClientB 16><IPClientA 4><MagicValue91 1><RandomKeyPartClientA 2>) 23
34 - Client B (Incomming 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 safe CPU time
39 -> The handshake is encrypted - except otherwise noted - by the Keys created above
40 -> Padding is cucrently 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 compromiss, 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 (Incomming 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 safe CPU time
58 -> The handshake is encrypted - except otherwise noted - by the Keys created above
59 -> Padding is cucrently 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 Obfusication:
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 compromiss, 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 (Incomming connection):
77 Receivekey: Md5(<KadID 16><RandomKeyPartClientA 2>) 18
78 - Note: The first 1024 Bytes will be _NOT_ discarded for UDP keys to safe CPU time
81 -> The handshake is encrypted - except otherwise noted - by the Keys created above
82 -> Padding is cucrently 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 compromiss, 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"
102 #include <protocol/Protocols.h>
103 #include <common/MD5Sum.h>
106 #include "CryptoPP_Inc.h" // Needed for Crypto functions
108 #define CRYPT_HEADER_WITHOUTPADDING 8
109 #define MAGICVALUE_UDP 91
110 #define MAGICVALUE_UDP_SYNC_CLIENT 0x395F2EC1
111 #define MAGICVALUE_UDP_SYNC_SERVER 0x13EF24D5
112 #define MAGICVALUE_UDP_SERVERCLIENT 0xA5
113 #define MAGICVALUE_UDP_CLIENTSERVER 0x6B
115 CEncryptedDatagramSocket::CEncryptedDatagramSocket( wxIPaddress
&address
, wxSocketFlags flags
, const CProxyData
*proxyData
) : CDatagramSocketProxy(address
, flags
, proxyData
)
120 CEncryptedDatagramSocket::~CEncryptedDatagramSocket()
125 int CEncryptedDatagramSocket::DecryptReceivedClient(uint8
* pbyBufIn
, int nBufLen
, uint8
** ppbyBufOut
, uint32 dwIP
, uint16
* nReceiverVerifyKey
, uint16
* nSenderVerifyKey
) {
126 int nResult
= nBufLen
;
127 *ppbyBufOut
= pbyBufIn
;
129 if (nResult
<= CRYPT_HEADER_WITHOUTPADDING
/*|| !thePrefs.IsClientCryptLayerSupported()*/)
132 if (nReceiverVerifyKey
== NULL
|| nSenderVerifyKey
== NULL
){
137 switch (pbyBufIn
[0]){
139 case OP_KADEMLIAPACKEDPROT
:
140 case OP_KADEMLIAHEADER
:
141 case OP_UDPRESERVEDPROT1
:
142 case OP_UDPRESERVEDPROT2
:
144 return nResult
; // no encrypted packet (see description on top)
149 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
150 // might be an encrypted packet, try to decrypt
152 CRC4EncryptableBuffer receivebuffer
;
154 bool bFlipTry
= false;
156 bKad
= bFlipTry
? !bKad
: bKad
;
160 if (Kademlia::CKademlia::GetPrefs()) {
161 uint8 achKeyData
[18];
162 memcpy(achKeyData
, Kademlia::CKademlia::GetPrefs()->GetKadID().GetData(), 16);
163 memcpy(achKeyData
+ 16, pbyBufIn
+ 1, 2); // random key part sent from remote client
164 md5
.Calculate(achKeyData
, sizeof(achKeyData
));
167 uint8 achKeyData
[23];
168 md4cpy(achKeyData
, thePrefs::GetUserHash().GetHash());
169 achKeyData
[20] = MAGICVALUE_UDP
;
170 PokeUInt32(achKeyData
+ 16, dwIP
);
171 memcpy(achKeyData
+ 21, pbyBufIn
+ 1, 2); // random key part sent from remote client
172 md5
.Calculate(achKeyData
, sizeof(achKeyData
));
175 receivebuffer
.SetKey(md5
, true);
176 receivebuffer
.RC4Crypt(pbyBufIn
+ 3, (uint8
*)&dwValue
, sizeof(dwValue
));
177 ENDIAN_SWAP_I_32(dwValue
);
179 bFlipTry
= !bFlipTry
; // next round try the other possibility
180 } while (dwValue
!= MAGICVALUE_UDP_SYNC_CLIENT
&& bFlipTry
); // try to decrypt as ed2k as well as kad packet if needed (max 2 rounds)
182 if (dwValue
== MAGICVALUE_UDP_SYNC_CLIENT
){
183 // Yup this is an encrypted packet
184 //DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from clientIP: %s"), ipstr(dwIP)) );
187 receivebuffer
.RC4Crypt(pbyBufIn
+ 7, (uint8
*)&byPadLen
, 1);
188 nResult
-= CRYPT_HEADER_WITHOUTPADDING
;
190 if (nResult
<= byPadLen
){
191 //DebugLogError(_T("Invalid obfuscated UDP packet from clientIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dwIP), byPadLen);
192 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
196 receivebuffer
.RC4Crypt(NULL
, NULL
, byPadLen
);
203 //DebugLogError(_T("Obfuscated Kad packet with mismatching size (verify keys missing) received from clientIP: %s"), ipstr(dwIP));
204 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk;
206 // read the verify keys
207 *nReceiverVerifyKey
= PeekUInt16(pbyBufIn
+ CRYPT_HEADER_WITHOUTPADDING
+ byPadLen
);
208 *nSenderVerifyKey
= PeekUInt16(pbyBufIn
+ CRYPT_HEADER_WITHOUTPADDING
+ byPadLen
+ 2);
211 *nReceiverVerifyKey
= 0;
212 *nSenderVerifyKey
= 0;
215 *ppbyBufOut
= pbyBufIn
+ (nBufLen
- nResult
);
217 receivebuffer
.RC4Crypt((uint8
*)*ppbyBufOut
, (uint8
*)*ppbyBufOut
, nResult
);
218 //theStats.AddDownDataOverheadCrypt(nBufLen - nResult);
219 return nResult
; // done
221 //DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from clientIP: %s"), ipstr(dwIP));
222 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
226 int CEncryptedDatagramSocket::EncryptSendClient(uint8
** ppbyBuf
, int nBufLen
, const uint8
* pachClientHashOrKadID
, bool bKad
, uint16 nReceiverVerifyKey
, uint16 nSenderVerifyKey
) {
227 wxASSERT( theApp
->GetPublicIP() != 0 || bKad
);
228 wxASSERT( thePrefs::IsClientCryptLayerSupported() );
230 uint8 byPadLen
= 0; // padding disabled for UDP currently
231 const uint32 nCryptHeaderLen
= byPadLen
+ CRYPT_HEADER_WITHOUTPADDING
+ (bKad
? 4 : 0);
232 uint32 nCryptedLen
= nBufLen
+ nCryptHeaderLen
;
233 uint8
* pachCryptedBuffer
= new uint8
[nCryptedLen
];
235 uint16 nRandomKeyPart
= GetRandomUint16();
236 CRC4EncryptableBuffer sendbuffer
;
239 uint8 achKeyData
[18];
240 md4cpy(achKeyData
, pachClientHashOrKadID
);
241 PokeUInt16(achKeyData
+16, nRandomKeyPart
);
242 md5
.Calculate(achKeyData
, sizeof(achKeyData
));
244 uint8 achKeyData
[23];
245 md4cpy(achKeyData
, pachClientHashOrKadID
);
246 PokeUInt32(achKeyData
+16, theApp
->GetPublicIP());
247 PokeUInt16(achKeyData
+21, nRandomKeyPart
);
248 achKeyData
[20] = MAGICVALUE_UDP
;
249 md5
.Calculate(achKeyData
, sizeof(achKeyData
));
252 sendbuffer
.SetKey(md5
, true);
254 // create the semi random byte encryption header
255 uint8 bySemiRandomNotProtocolMarker
= 0;
257 for (i
= 0; i
< 128; i
++){
258 bySemiRandomNotProtocolMarker
= GetRandomUint8();
259 bySemiRandomNotProtocolMarker
= bKad
? (bySemiRandomNotProtocolMarker
& 0xFE) : (bySemiRandomNotProtocolMarker
| 0x01); // set the ed2k/kad marker bit
262 switch (bySemiRandomNotProtocolMarker
){ // not allowed values
264 case OP_KADEMLIAPACKEDPROT
:
265 case OP_KADEMLIAHEADER
:
266 case OP_UDPRESERVEDPROT1
:
267 case OP_UDPRESERVEDPROT2
:
280 // either we have _real_ bad luck or the randomgenerator is a bit messed up
282 bySemiRandomNotProtocolMarker
= 0x01;
285 pachCryptedBuffer
[0] = bySemiRandomNotProtocolMarker
;
286 PokeUInt16(pachCryptedBuffer
+ 1, nRandomKeyPart
);
288 uint32 dwMagicValue
= ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_CLIENT
);
289 sendbuffer
.RC4Crypt((uint8
*)&dwMagicValue
, pachCryptedBuffer
+ 3, 4);
291 sendbuffer
.RC4Crypt((uint8
*)&byPadLen
, pachCryptedBuffer
+ 7, 1);
293 for (int j
= 0; j
< byPadLen
; j
++){
294 uint8 byRand
= (uint8
)rand(); // they actually dont really need to be random, but it doesn't hurts either
295 sendbuffer
.RC4Crypt((uint8
*)&byRand
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ j
, 1);
299 sendbuffer
.RC4Crypt((uint8
*)&nReceiverVerifyKey
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ byPadLen
, 2);
300 sendbuffer
.RC4Crypt((uint8
*)&nSenderVerifyKey
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ byPadLen
+ 2, 2);
303 sendbuffer
.RC4Crypt(*ppbyBuf
, pachCryptedBuffer
+ nCryptHeaderLen
, nBufLen
);
305 *ppbyBuf
= pachCryptedBuffer
;
307 //theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);
311 int CEncryptedDatagramSocket::DecryptReceivedServer(
313 int nBufLen
, uint8
**ppbyBufOut
,
317 int nResult
= nBufLen
;
318 *ppbyBufOut
= pbyBufIn
;
320 if (nResult
<= CRYPT_HEADER_WITHOUTPADDING
|| !thePrefs::IsServerCryptLayerUDPEnabled() || dwBaseKey
== 0) {
324 if(pbyBufIn
[0] == OP_EDONKEYPROT
) {
325 return nResult
; // no encrypted packet (see description on top)
328 // might be an encrypted packet, try to decrypt
330 PokeUInt32(achKeyData
, dwBaseKey
);
331 achKeyData
[4] = MAGICVALUE_UDP_SERVERCLIENT
;
332 memcpy(achKeyData
+ 5, pbyBufIn
+ 1, 2); // random key part sent from remote server
334 CRC4EncryptableBuffer receivebuffer
;
335 MD5Sum
md5(achKeyData
, sizeof(achKeyData
));
336 receivebuffer
.SetKey(md5
,true);
339 receivebuffer
.RC4Crypt(pbyBufIn
+ 3, (uint8
*)&dwValue
, sizeof(dwValue
));
340 ENDIAN_SWAP_I_32(dwValue
);
341 if (dwValue
== MAGICVALUE_UDP_SYNC_SERVER
){
342 // yup this is an encrypted packet
343 //DEBUG_ONLY( DebugLog(_T("Received obfuscated UDP packet from ServerIP: %s"), ipstr(dbgIP)) );
345 receivebuffer
.RC4Crypt(pbyBufIn
+ 7, (uint8
*)&byPadLen
, 1);
347 nResult
-= CRYPT_HEADER_WITHOUTPADDING
;
349 if (nResult
<= byPadLen
){
350 //DebugLogError(_T("Invalid obfuscated UDP packet from ServerIP: %s, Paddingsize (%u) larger than received bytes"), ipstr(dbgIP), byPadLen);
351 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
355 receivebuffer
.RC4Crypt(NULL
, NULL
, byPadLen
);
359 *ppbyBufOut
= pbyBufIn
+ (nBufLen
- nResult
);
360 receivebuffer
.RC4Crypt((uint8
*)*ppbyBufOut
, (uint8
*)*ppbyBufOut
, nResult
);
362 //theStats.AddDownDataOverheadCrypt(nBufLen - nResult);
363 return nResult
; // done
365 //DebugLogWarning(_T("Obfuscated packet expected but magicvalue mismatch on UDP packet from ServerIP: %s"), ipstr(dbgIP));
366 return nBufLen
; // pass through, let the Receivefunction do the errorhandling on this junk
370 int CEncryptedDatagramSocket::EncryptSendServer(uint8
** ppbyBuf
, int nBufLen
, uint32 dwBaseKey
) {
371 wxASSERT( thePrefs::IsServerCryptLayerUDPEnabled() );
372 wxASSERT( dwBaseKey
!= 0 );
374 uint8 byPadLen
= 0; // padding disabled for UDP currently
375 uint32 nCryptedLen
= nBufLen
+ byPadLen
+ CRYPT_HEADER_WITHOUTPADDING
;
376 uint8
* pachCryptedBuffer
= new uint8
[nCryptedLen
];
378 uint16 nRandomKeyPart
= GetRandomUint16();
381 PokeUInt32(achKeyData
, dwBaseKey
);
382 achKeyData
[4] = MAGICVALUE_UDP_CLIENTSERVER
;
383 PokeUInt16(achKeyData
+ 5, nRandomKeyPart
);
384 MD5Sum
md5(achKeyData
, sizeof(achKeyData
));
385 CRC4EncryptableBuffer sendbuffer
;
386 sendbuffer
.SetKey(md5
);
388 // create the semi random byte encryption header
389 uint8 bySemiRandomNotProtocolMarker
= 0;
392 for (i
= 0; i
< 128; i
++){
393 bySemiRandomNotProtocolMarker
= GetRandomUint8();
394 if (bySemiRandomNotProtocolMarker
!= OP_EDONKEYPROT
) { // not allowed values
400 // either we have _real_ bad luck or the randomgenerator is a bit messed up
402 bySemiRandomNotProtocolMarker
= 0x01;
405 pachCryptedBuffer
[0] = bySemiRandomNotProtocolMarker
;
406 PokeUInt16(pachCryptedBuffer
+ 1, nRandomKeyPart
);
408 uint32 dwMagicValue
= ENDIAN_SWAP_32(MAGICVALUE_UDP_SYNC_SERVER
);
409 sendbuffer
.RC4Crypt((uint8
*)&dwMagicValue
, pachCryptedBuffer
+ 3, 4);
411 sendbuffer
.RC4Crypt((uint8
*)&byPadLen
, pachCryptedBuffer
+ 7, 1);
413 for (int j
= 0; j
< byPadLen
; j
++){
414 uint8 byRand
= (uint8
)rand(); // they actually dont really need to be random, but it doesn't hurts either
415 sendbuffer
.RC4Crypt((uint8
*)&byRand
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ j
, 1);
417 sendbuffer
.RC4Crypt(*ppbyBuf
, pachCryptedBuffer
+ CRYPT_HEADER_WITHOUTPADDING
+ byPadLen
, nBufLen
);
419 *ppbyBuf
= pachCryptedBuffer
;
421 //theStats.AddUpDataOverheadCrypt(nCryptedLen - nBufLen);