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/* This class supports obfuscation and encryption for a *Mule tcp connection.
27   Right now only basic obfusication is supported, but this can be expanded, as their is a
28   dedicated handshake to negotiate the encryption method used.
29
30   Please note, even if obfuscation uses encryption methods, it does not fulfill cryptographic standards since it
31   doesn't use secret (and for rc4 important: unique) keys
32*/
33
34#ifndef __ENCRYPTEDSTREAMSOCKET_H__
35#define __ENCRYPTEDSTREAMSOCKET_H__
36
37#include <wx/wx.h>
38#include <wx/string.h>
39
40// cryptoPP used for DH integer calculations
41#include "CryptoPP_Inc.h"	// Needed for Crypto functions
42#include "Proxy.h"
43#include "Types.h"
44
45#include "RC4Encrypt.h"
46
47#define ERR_WRONGHEADER			0x01
48#define ERR_TOOBIG			0x02
49#define ERR_ENCRYPTION			0x03
50#define ERR_ENCRYPTION_NOTALLOWED	0x04
51
52enum EStreamCryptState {
53	ECS_NONE = 0,			// Disabled or not available
54	ECS_UNKNOWN,			// Incoming connection, will test the first incoming data for encrypted protocol
55	ECS_PENDING,			// Outgoing connection, will start sending encryption protocol
56	ECS_PENDING_SERVER,		// Outgoing serverconnection, will start sending encryption protocol
57	ECS_NEGOTIATING,		// Encryption supported, handshake still uncompleted
58	ECS_ENCRYPTING			// Encryption enabled
59};
60
61enum ENegotiatingState {
62	ONS_NONE,
63
64	ONS_BASIC_CLIENTA_RANDOMPART,
65	ONS_BASIC_CLIENTA_MAGICVALUE,
66	ONS_BASIC_CLIENTA_METHODTAGSPADLEN,
67	ONS_BASIC_CLIENTA_PADDING,
68
69	ONS_BASIC_CLIENTB_MAGICVALUE,
70	ONS_BASIC_CLIENTB_METHODTAGSPADLEN,
71	ONS_BASIC_CLIENTB_PADDING,
72
73	ONS_BASIC_SERVER_DHANSWER,
74	ONS_BASIC_SERVER_MAGICVALUE,
75	ONS_BASIC_SERVER_METHODTAGSPADLEN,
76	ONS_BASIC_SERVER_PADDING,
77	ONS_BASIC_SERVER_DELAYEDSENDING,
78
79	ONS_COMPLETE
80};
81
82enum EEncryptionMethods {
83	ENM_OBFUSCATION = 0x00
84};
85
86
87class CEncryptedStreamSocket : public CSocketClientProxy
88{
89public:
90	CEncryptedStreamSocket(wxSocketFlags flags = wxSOCKET_NONE, const CProxyData *proxyData = NULL);
91	virtual ~CEncryptedStreamSocket();
92
93	void SetConnectionEncryption(bool bEnabled, const uint8_t *pTargetClientHash, bool bServerConnection);
94
95	//! Indicates how many bytes were received including obfuscation,
96	//! so that the parent knows if the receive limit was reached
97	uint32_t GetRealReceivedBytes() const		{ return m_nObfusicationBytesReceived; }
98
99	bool	IsObfusicating() const			{ return m_StreamCryptState == ECS_ENCRYPTING && m_EncryptionMethod == ENM_OBFUSCATION; }
100	bool	IsServerCryptEnabledConnection() const	{ return m_bServerCrypt; }
101
102	uint8_t	m_dbgbyEncryptionSupported;
103	uint8_t	m_dbgbyEncryptionRequested;
104	uint8_t	m_dbgbyEncryptionMethodSet;
105
106protected:
107	int	Write(const void* lpBuf, uint32_t nBufLen);
108	int	Read(void* lpBuf, uint32_t nBufLen);
109
110	virtual void OnError(int /*nErrorCode*/) {};
111	virtual void OnSend(int nErrorCode);
112
113	wxString	DbgGetIPString();
114	void		CryptPrepareSendData(uint8_t* pBuffer, uint32_t nLen);
115	bool		IsEncryptionLayerReady();
116	uint8_t		GetSemiRandomNotProtocolMarker() const;
117
118	uint32_t		m_nObfusicationBytesReceived;
119	EStreamCryptState	m_StreamCryptState;
120	EEncryptionMethods	m_EncryptionMethod;
121	bool			m_bFullReceive;
122	bool			m_bServerCrypt;
123
124private:
125	int	Negotiate(const uint8_t* pBuffer, uint32_t nLen);
126	void	StartNegotiation(bool bOutgoing);
127	int	SendNegotiatingData(const void *lpBuf, uint32_t nBufLen, uint32_t nStartCryptFromByte = 0, bool bDelaySend = false);
128
129	ENegotiatingState	m_NegotiatingState;
130	CRC4EncryptableBuffer	m_pfiReceiveBuffer;
131	uint32_t		m_nReceiveBytesWanted;
132	CRC4EncryptableBuffer	m_pfiSendBuffer;
133	uint32_t		m_nRandomKeyPart;
134	CryptoPP::Integer	m_cryptDHA;
135};
136
137#endif // __ENCRYPTEDSTREAMSOCKET_H__
138