1 /*
2     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 #include "encryptedauthenticate.h"
7 
8 #include <QRandomGenerator>
9 #include <algorithm>
10 
11 #include "encryptedpacketsocket.h"
12 #include "functions.h"
13 #include "rc4encryptor.h"
14 #include <net/socks.h>
15 #include <torrent/globals.h>
16 #include <torrent/server.h>
17 #include <util/functions.h>
18 #include <util/log.h>
19 
20 using namespace bt;
21 
22 namespace mse
23 {
EncryptedAuthenticate(const net::Address & addr,TransportProtocol proto,const SHA1Hash & info_hash,const PeerID & peer_id,PeerConnector::WPtr pcon)24 EncryptedAuthenticate::EncryptedAuthenticate(const net::Address &addr,
25                                              TransportProtocol proto,
26                                              const SHA1Hash &info_hash,
27                                              const PeerID &peer_id,
28                                              PeerConnector::WPtr pcon)
29     : Authenticate(addr, proto, info_hash, peer_id, pcon)
30 {
31     mse::GeneratePublicPrivateKey(xa, ya);
32     state = NOT_CONNECTED;
33     buf_size = 0;
34     our_rc4 = nullptr;
35     vc_off = 0;
36     dec_bytes = 0;
37     crypto_select = 0;
38     pad_D_len = 0;
39     end_of_crypto_handshake = 0;
40     // Out(SYS_CON|LOG_DEBUG) << "EncryptedAuthenticate : " << ip << ":" << port << endl;
41 }
42 
~EncryptedAuthenticate()43 EncryptedAuthenticate::~EncryptedAuthenticate()
44 {
45     delete our_rc4;
46 }
47 
connected()48 void EncryptedAuthenticate::connected()
49 {
50     // we are connected so send ya and some padding
51     Uint8 tmp[608];
52     ya.toBuffer(tmp, 96);
53     sock->sendData(tmp, 96 + QRandomGenerator::global()->bounded(512));
54     state = SENT_YA;
55 }
56 
57 /*
58 1 A->B: Diffie Hellman Ya, PadA
59 2 B->A: Diffie Hellman Yb, PadB
60 3 A->B: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA)
61 4 B->A: ENCRYPT(VC, crypto_select, len(padD), padD), ENCRYPT2(Payload Stream)
62 5 A->B: ENCRYPT2(Payload Stream)
63 */
64 
handleYB()65 void EncryptedAuthenticate::handleYB()
66 {
67     // if you can't sent 96 bytes you are not worth the effort
68     if (buf_size < 96) {
69         Out(SYS_CON | LOG_DEBUG) << "Not enough data received, encrypted authentication failed" << endl;
70         onFinish(false);
71         return;
72     }
73 
74     // read Yb
75     yb = BigInt::fromBuffer(buf, 96);
76 
77     // calculate s
78     s = mse::DHSecret(xa, yb);
79 
80     state = GOT_YB;
81     // now we must send line 3
82     Uint8 tmp_buf[120]; // temporary buffer
83     bt::SHA1Hash h1, h2; // temporary hash
84 
85     // generate and send the first hash
86     memcpy(tmp_buf, "req1", 4);
87     s.toBuffer(tmp_buf + 4, 96);
88     h1 = SHA1Hash::generate(tmp_buf, 100);
89     sock->sendData(h1.getData(), 20);
90 
91     // generate second and third hash and xor them
92     memcpy(tmp_buf, "req2", 4);
93     memcpy(tmp_buf + 4, info_hash.getData(), 20);
94     h1 = SHA1Hash::generate(tmp_buf, 24);
95 
96     memcpy(tmp_buf, "req3", 4);
97     s.toBuffer(tmp_buf + 4, 96);
98     h2 = SHA1Hash::generate(tmp_buf, 100);
99     sock->sendData((h1 ^ h2).getData(), 20);
100 
101     // now we enter encrypted mode the keys are :
102     // HASH('keyA', S, SKEY) for the encryption key
103     // HASH('keyB', S, SKEY) for the decryption key
104     enc = mse::EncryptionKey(true, s, info_hash);
105     dec = mse::EncryptionKey(false, s, info_hash);
106 
107     our_rc4 = new RC4Encryptor(dec, enc);
108 
109     // now we must send ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA))
110     memset(tmp_buf, 0, 16); // VC are 8 0x00's
111     if (bt::ServerInterface::unencryptedConnectionsAllowed())
112         tmp_buf[11] = 0x03; // we support both plain text and rc4
113     else
114         tmp_buf[11] = 0x02;
115     WriteUint16(tmp_buf, 12, 0x0000); // no padC
116     WriteUint16(tmp_buf, 14, 68); // length of IA, which will be the bittorrent handshake
117     // send IA which is the handshake
118     makeHandshake(tmp_buf + 16, info_hash, our_peer_id);
119     sock->sendData(our_rc4->encrypt(tmp_buf, 84), 84);
120 
121     // search for the encrypted VC in the data
122     findVC();
123 }
124 
findVC()125 void EncryptedAuthenticate::findVC()
126 {
127     Uint8 vc[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
128 
129     RC4Encryptor rc4(enc, dec);
130     memcpy(vc, rc4.encrypt(vc, 8), 8);
131 
132     Uint32 max_i = buf_size - 8;
133     for (Uint32 i = 96; i < max_i; i++) {
134         if (vc[0] == buf[i] && memcmp(buf + i, vc, 8) == 0) {
135             state = FOUND_VC;
136             vc_off = i;
137             handleCryptoSelect();
138             return;
139         }
140     }
141 
142     // we haven't found it in the first 616 bytes (96 + max 512 padding + 8 bytes VC)
143     if (buf_size >= 616) {
144         onFinish(false);
145     }
146 }
147 
handleCryptoSelect()148 void EncryptedAuthenticate::handleCryptoSelect()
149 {
150     // not enough data available so lets come back later
151     if (vc_off + 14 >= buf_size)
152         return;
153 
154     // now decrypt the first 14 bytes
155     our_rc4->decrypt(buf + vc_off, 14);
156     // check the VC
157     for (Uint32 i = vc_off; i < vc_off + 8; i++) {
158         if (buf[i]) {
159             Out(SYS_CON | LOG_DEBUG) << "Invalid VC " << endl;
160             onFinish(false);
161             return;
162         }
163     }
164 
165     crypto_select = ReadUint32(buf, vc_off + 8);
166     pad_D_len = ReadUint16(buf, vc_off + 12);
167     if (pad_D_len > 512) {
168         Out(SYS_CON | LOG_DEBUG) << "Invalid pad D length" << endl;
169         onFinish(false);
170         return;
171     }
172 
173     end_of_crypto_handshake = vc_off + 14 + pad_D_len;
174     if (!(vc_off + 14 + pad_D_len < buf_size)) {
175         // padD is not complete, wait for that
176         state = WAIT_FOR_PAD_D;
177         return;
178     }
179 
180     handlePadD();
181 }
182 
handlePadD()183 void EncryptedAuthenticate::handlePadD()
184 {
185     // decrypt the padding
186     our_rc4->decrypt(buf + (vc_off + 14), pad_D_len);
187 
188     if (crypto_select & 0x00000001) { // plain_text selected
189         delete our_rc4;
190         our_rc4 = nullptr;
191     } else if (crypto_select & 0x00000002) { // now it must be rc4 if not exit
192         sock->setRC4Encryptor(our_rc4);
193         our_rc4 = nullptr;
194     } else { // we don't support anything else so error out
195         onFinish(false);
196         return;
197     }
198 
199     // noz we wait for the normal handshake
200     state = NORMAL_HANDSHAKE;
201     // if we have read more then the crypto handshake, reinsert it
202     if (buf_size > vc_off + 14 + pad_D_len) {
203         Uint32 off = vc_off + 14 + pad_D_len;
204         sock->reinsert(buf + off, buf_size - off);
205         Authenticate::onReadyRead();
206     }
207 }
208 
onReadyRead()209 void EncryptedAuthenticate::onReadyRead()
210 {
211     if (finished)
212         return;
213 
214     if (socks) {
215         switch (socks->onReadyToRead()) {
216         case net::Socks::FAILED:
217             Out(SYS_CON | LOG_NOTICE) << "Failed to connect to host via socks server " << endl;
218             onFinish(false);
219             break;
220         case net::Socks::CONNECTED:
221             // connection established, so get rid of socks shit
222             delete socks;
223             socks = nullptr;
224             connected();
225             if (sock->bytesAvailable() > 0)
226                 onReadyRead();
227             break;
228         default:
229             break;
230         }
231         return;
232     }
233 
234     Uint32 ba = sock->bytesAvailable();
235     if (ba == 0) {
236         onFinish(false);
237         return;
238     }
239 
240     if (state != NORMAL_HANDSHAKE) {
241         if (buf_size + ba > MAX_EA_BUF_SIZE)
242             ba = MAX_EA_BUF_SIZE - buf_size;
243 
244         // do not read past the end of padD
245         if (pad_D_len > 0 && buf_size + ba > vc_off + 14 + pad_D_len)
246             ba = (vc_off + 14 + pad_D_len) - buf_size;
247         // read data
248         buf_size += sock->readData(buf + buf_size, ba);
249     }
250 
251     switch (state) {
252     case SENT_YA:
253         if (ba > 608) {
254             onFinish(false);
255         } else {
256             handleYB();
257         }
258         break;
259     case GOT_YB:
260         findVC();
261         break;
262     case FOUND_VC:
263         handleCryptoSelect();
264         break;
265     case WAIT_FOR_PAD_D:
266         handlePadD();
267         break;
268     case NORMAL_HANDSHAKE:
269         // let AuthenticateBase deal with the data
270         AuthenticateBase::onReadyRead();
271         break;
272     default:
273         break;
274     };
275 }
276 
277 }
278