1 /* <!-- copyright */
2 /*
3 * aria2 - The high speed download utility
4 *
5 * Copyright (C) 2006 Tatsuhiro Tsujikawa
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * In addition, as a special exception, the copyright holders give
22 * permission to link the code of portions of this program with the
23 * OpenSSL library under certain conditions as described in each
24 * individual source file, and distribute linked combinations
25 * including the two.
26 * You must obey the GNU General Public License in all respects
27 * for all of the code used other than OpenSSL. If you modify
28 * file(s) with this exception, you may extend this exception to your
29 * version of the file(s), but you are not obligated to do so. If you
30 * do not wish to do so, delete this exception statement from your
31 * version. If you delete this exception statement from all source
32 * files in the program, then also delete it here.
33 */
34 /* copyright --> */
35 #include "MSEHandshake.h"
36
37 #include <array>
38 #include <cstring>
39 #include <cassert>
40
41 #include "message.h"
42 #include "DlAbortEx.h"
43 #include "LogFactory.h"
44 #include "Logger.h"
45 #include "BtHandshakeMessage.h"
46 #include "SocketCore.h"
47 #include "a2netcompat.h"
48 #include "DHKeyExchange.h"
49 #include "ARC4Encryptor.h"
50 #include "MessageDigest.h"
51 #include "message_digest_helper.h"
52 #include "SimpleRandomizer.h"
53 #include "util.h"
54 #include "DownloadContext.h"
55 #include "prefs.h"
56 #include "Option.h"
57 #include "fmt.h"
58 #include "bittorrent_helper.h"
59 #include "array_fun.h"
60
61 namespace aria2 {
62
63 namespace {
64
65 const size_t MAX_PAD_LENGTH = 512;
66 const size_t CRYPTO_BITFIELD_LENGTH = 4;
67 constexpr auto VC = std::array<unsigned char, MSEHandshake::VC_LENGTH>{};
68
69 const unsigned char* PRIME = reinterpret_cast<const unsigned char*>(
70 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B"
71 "139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485"
72 "B576625E7EC6F44C42E9A63A36210000000000090563");
73 const unsigned char* GENERATOR = reinterpret_cast<const unsigned char*>("2");
74
75 } // namespace
76
MSEHandshake(cuid_t cuid,const std::shared_ptr<SocketCore> & socket,const Option * op)77 MSEHandshake::MSEHandshake(cuid_t cuid,
78 const std::shared_ptr<SocketCore>& socket,
79 const Option* op)
80 : cuid_(cuid),
81 socket_(socket),
82 wantRead_(false),
83 option_(op),
84 rbufLength_(0),
85 socketBuffer_(socket),
86 negotiatedCryptoType_(CRYPTO_NONE),
87 initiator_(true),
88 markerIndex_(0),
89 padLength_(0),
90 iaLength_(0),
91 sha1_(MessageDigest::sha1())
92 {
93 }
94
95 MSEHandshake::~MSEHandshake() = default;
96
identifyHandshakeType()97 MSEHandshake::HANDSHAKE_TYPE MSEHandshake::identifyHandshakeType()
98 {
99 if (rbufLength_ < 20) {
100 wantRead_ = true;
101 return HANDSHAKE_NOT_YET;
102 }
103 if (rbuf_[0] == BtHandshakeMessage::PSTR_LENGTH &&
104 memcmp(BtHandshakeMessage::BT_PSTR, rbuf_ + 1, 19) == 0) {
105 A2_LOG_DEBUG(
106 fmt("CUID#%" PRId64 " - This is legacy BitTorrent handshake.", cuid_));
107 return HANDSHAKE_LEGACY;
108 }
109 A2_LOG_DEBUG(fmt(
110 "CUID#%" PRId64 " - This may be encrypted BitTorrent handshake.", cuid_));
111 return HANDSHAKE_ENCRYPTED;
112 }
113
initEncryptionFacility(bool initiator)114 void MSEHandshake::initEncryptionFacility(bool initiator)
115 {
116 dh_ = make_unique<DHKeyExchange>();
117 dh_->init(PRIME, PRIME_BITS, GENERATOR, 160);
118 dh_->generatePublicKey();
119 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - DH initialized.", cuid_));
120 initiator_ = initiator;
121 }
122
sendPublicKey()123 void MSEHandshake::sendPublicKey()
124 {
125 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Sending public key.", cuid_));
126 auto buf = std::vector<unsigned char>(KEY_LENGTH + MAX_PAD_LENGTH);
127 dh_->getPublicKey(buf.data(), KEY_LENGTH);
128
129 size_t padLength =
130 SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH + 1);
131 dh_->generateNonce(buf.data() + KEY_LENGTH, padLength);
132 buf.resize(KEY_LENGTH + padLength);
133
134 socketBuffer_.pushBytes(std::move(buf));
135 }
136
read()137 void MSEHandshake::read()
138 {
139 if (rbufLength_ >= MAX_BUFFER_LENGTH) {
140 assert(!wantRead_);
141 return;
142 }
143 size_t len = MAX_BUFFER_LENGTH - rbufLength_;
144 socket_->readData(rbuf_ + rbufLength_, len);
145 if (len == 0 && !socket_->wantRead() && !socket_->wantWrite()) {
146 // TODO Should we set graceful in peer?
147 throw DL_ABORT_EX(EX_EOF_FROM_PEER);
148 }
149 rbufLength_ += len;
150 wantRead_ = false;
151 }
152
send()153 bool MSEHandshake::send()
154 {
155 socketBuffer_.send();
156 return socketBuffer_.sendBufferIsEmpty();
157 }
158
shiftBuffer(size_t offset)159 void MSEHandshake::shiftBuffer(size_t offset)
160 {
161 assert(rbufLength_ >= offset);
162 memmove(rbuf_, rbuf_ + offset, rbufLength_ - offset);
163 rbufLength_ -= offset;
164 }
165
receivePublicKey()166 bool MSEHandshake::receivePublicKey()
167 {
168 if (rbufLength_ < KEY_LENGTH) {
169 wantRead_ = true;
170 return false;
171 }
172 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - public key received.", cuid_));
173 // TODO handle exception. in catch, resbufLength = 0;
174 dh_->computeSecret(secret_, sizeof(secret_), rbuf_, KEY_LENGTH);
175 // shift buffer
176 shiftBuffer(KEY_LENGTH);
177 return true;
178 }
179
initCipher(const unsigned char * infoHash)180 void MSEHandshake::initCipher(const unsigned char* infoHash)
181 {
182 memcpy(infoHash_, infoHash, INFO_HASH_LENGTH);
183 // Initialize cipher
184 unsigned char s[4 + KEY_LENGTH + INFO_HASH_LENGTH];
185 memcpy(s, initiator_ ? "keyA" : "keyB", 4);
186 memcpy(s + 4, secret_, KEY_LENGTH);
187 memcpy(s + 4 + KEY_LENGTH, infoHash, INFO_HASH_LENGTH);
188
189 unsigned char localCipherKey[20];
190 sha1_->reset();
191 message_digest::digest(localCipherKey, sizeof(localCipherKey), sha1_.get(), s,
192 sizeof(s));
193 encryptor_ = make_unique<ARC4Encryptor>();
194 encryptor_->init(localCipherKey, sizeof(localCipherKey));
195
196 unsigned char peerCipherKey[20];
197 memcpy(s, initiator_ ? "keyB" : "keyA", 4);
198 sha1_->reset();
199 message_digest::digest(peerCipherKey, sizeof(peerCipherKey), sha1_.get(), s,
200 sizeof(s));
201 decryptor_ = make_unique<ARC4Encryptor>();
202 decryptor_->init(peerCipherKey, sizeof(peerCipherKey));
203
204 // discard first 1024 bytes ARC4 output.
205 std::array<unsigned char, 1_k> garbage;
206 encryptor_->encrypt(garbage.size(), garbage.data(), garbage.data());
207 decryptor_->encrypt(garbage.size(), garbage.data(), garbage.data());
208
209 if (initiator_) {
210 ARC4Encryptor enc;
211 enc.init(peerCipherKey, sizeof(peerCipherKey));
212 // discard first 1024 bytes ARC4 output.
213 enc.encrypt(garbage.size(), garbage.data(), garbage.data());
214 enc.encrypt(VC_LENGTH, initiatorVCMarker_, VC.data());
215 }
216 }
217
218 // Given data is pushed to socketBuffer_ and data will be deleted by
219 // socketBuffer_.
encryptAndSendData(std::vector<unsigned char> data)220 void MSEHandshake::encryptAndSendData(std::vector<unsigned char> data)
221 {
222 encryptor_->encrypt(data.size(), data.data(), data.data());
223 socketBuffer_.pushBytes(std::move(data));
224 }
225
createReq1Hash(unsigned char * md) const226 void MSEHandshake::createReq1Hash(unsigned char* md) const
227 {
228 unsigned char buffer[100];
229 memcpy(buffer, "req1", 4);
230 memcpy(buffer + 4, secret_, KEY_LENGTH);
231 sha1_->reset();
232 message_digest::digest(md, 20, sha1_.get(), buffer, 4 + KEY_LENGTH);
233 }
234
createReq23Hash(unsigned char * md,const unsigned char * infoHash) const235 void MSEHandshake::createReq23Hash(unsigned char* md,
236 const unsigned char* infoHash) const
237 {
238 unsigned char x[24];
239 memcpy(x, "req2", 4);
240 memcpy(x + 4, infoHash, INFO_HASH_LENGTH);
241 unsigned char xh[20];
242 sha1_->reset();
243 message_digest::digest(xh, sizeof(xh), sha1_.get(), x, sizeof(x));
244
245 unsigned char y[4 + 96];
246 memcpy(y, "req3", 4);
247 memcpy(y + 4, secret_, KEY_LENGTH);
248 unsigned char yh[20];
249 sha1_->reset();
250 message_digest::digest(yh, sizeof(yh), sha1_.get(), y, sizeof(y));
251
252 for (size_t i = 0; i < 20; ++i) {
253 md[i] = xh[i] ^ yh[i];
254 }
255 }
256
decodeLength16(const unsigned char * buffer)257 uint16_t MSEHandshake::decodeLength16(const unsigned char* buffer)
258 {
259 uint16_t be;
260 decryptor_->encrypt(sizeof(be), reinterpret_cast<unsigned char*>(&be),
261 buffer);
262 return ntohs(be);
263 }
264
sendInitiatorStep2()265 void MSEHandshake::sendInitiatorStep2()
266 {
267 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Sending negotiation step2.", cuid_));
268 // Assuming no exception
269 auto md = std::vector<unsigned char>(20);
270 createReq1Hash(md.data());
271 socketBuffer_.pushBytes(std::move(md));
272 // Assuming no exception
273 md = std::vector<unsigned char>(20);
274 createReq23Hash(md.data(), infoHash_);
275 socketBuffer_.pushBytes(std::move(md));
276 // buffer is filled in this order:
277 // VC(VC_LENGTH bytes),
278 // crypto_provide(CRYPTO_BITFIELD_LENGTH bytes),
279 // len(padC)(2 bytes),
280 // padC(len(padC) bytes <= MAX_PAD_LENGTH),
281 // len(IA)(2 bytes)
282 auto buffer = std::vector<unsigned char>(VC_LENGTH + CRYPTO_BITFIELD_LENGTH +
283 2 + MAX_PAD_LENGTH + 2);
284 auto ptr = std::begin(buffer);
285 // VC
286 ptr += VC_LENGTH;
287 // crypto_provide
288 if (!option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) &&
289 option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
290 ptr[3] = CRYPTO_PLAIN_TEXT;
291 }
292 ptr[3] |= CRYPTO_ARC4;
293 ptr += CRYPTO_BITFIELD_LENGTH;
294 // len(padC)
295 uint16_t padCLength =
296 SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH + 1);
297 uint16_t padCLengthBE = htons(padCLength);
298 ptr = std::copy_n(reinterpret_cast<unsigned char*>(&padCLengthBE),
299 sizeof(padCLengthBE), ptr);
300 // padC
301 ptr += padCLength;
302 // len(IA)
303 // currently, IA is zero-length.
304 uint16_t iaLength = 0;
305 {
306 uint16_t iaLengthBE = htons(iaLength);
307 ptr = std::copy_n(reinterpret_cast<unsigned char*>(&iaLengthBE),
308 sizeof(iaLengthBE), ptr);
309 }
310 buffer.erase(ptr, std::end(buffer));
311 encryptAndSendData(std::move(buffer));
312 }
313
314 // This function reads exactly until the end of VC marker is reached.
findInitiatorVCMarker()315 bool MSEHandshake::findInitiatorVCMarker()
316 {
317 // 616 is synchronization point of initiator
318 // find vc
319 unsigned char* ptr =
320 std::search(&rbuf_[0], &rbuf_[rbufLength_], &initiatorVCMarker_[0],
321 &initiatorVCMarker_[VC_LENGTH]);
322 if (ptr == &rbuf_[rbufLength_]) {
323 if (616 - KEY_LENGTH <= rbufLength_) {
324 throw DL_ABORT_EX("Failed to find VC marker.");
325 }
326 else {
327 wantRead_ = true;
328 return false;
329 }
330 }
331 markerIndex_ = ptr - rbuf_;
332 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - VC marker found at %lu", cuid_,
333 static_cast<unsigned long>(markerIndex_)));
334 verifyVC(rbuf_ + markerIndex_);
335 // shift rbuf
336 shiftBuffer(markerIndex_ + VC_LENGTH);
337 return true;
338 }
339
receiveInitiatorCryptoSelectAndPadDLength()340 bool MSEHandshake::receiveInitiatorCryptoSelectAndPadDLength()
341 {
342 if (CRYPTO_BITFIELD_LENGTH + 2 /* PadD length*/ > rbufLength_) {
343 wantRead_ = true;
344 return false;
345 }
346 // verifyCryptoSelect
347 unsigned char* rbufptr = rbuf_;
348 decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr);
349 if ((rbufptr[3] & CRYPTO_PLAIN_TEXT) &&
350 !option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) &&
351 option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
352 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer prefers plaintext.", cuid_));
353 negotiatedCryptoType_ = CRYPTO_PLAIN_TEXT;
354 }
355 if (rbufptr[3] & CRYPTO_ARC4) {
356 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer prefers ARC4", cuid_));
357 negotiatedCryptoType_ = CRYPTO_ARC4;
358 }
359 if (negotiatedCryptoType_ == CRYPTO_NONE) {
360 throw DL_ABORT_EX(
361 fmt("CUID#%" PRId64 " - No supported crypto type selected.", cuid_));
362 }
363 // padD length
364 rbufptr += CRYPTO_BITFIELD_LENGTH;
365 padLength_ = verifyPadLength(rbufptr, "PadD");
366 // shift rbuf
367 shiftBuffer(CRYPTO_BITFIELD_LENGTH + 2 /* PadD length*/);
368 return true;
369 }
370
receivePad()371 bool MSEHandshake::receivePad()
372 {
373 if (padLength_ > rbufLength_) {
374 wantRead_ = true;
375 return false;
376 }
377 if (padLength_ == 0) {
378 return true;
379 }
380 decryptor_->encrypt(padLength_, rbuf_, rbuf_);
381 // shift rbuf_
382 shiftBuffer(padLength_);
383 return true;
384 }
385
findReceiverHashMarker()386 bool MSEHandshake::findReceiverHashMarker()
387 {
388 // 628 is synchronization limit of receiver.
389 // find hash('req1', S), S is secret_.
390 unsigned char md[20];
391 createReq1Hash(md);
392 unsigned char* ptr =
393 std::search(&rbuf_[0], &rbuf_[rbufLength_], &md[0], &md[sizeof(md)]);
394 if (ptr == &rbuf_[rbufLength_]) {
395 if (628 - KEY_LENGTH <= rbufLength_) {
396 throw DL_ABORT_EX("Failed to find hash marker.");
397 }
398 else {
399 wantRead_ = true;
400 return false;
401 }
402 }
403 markerIndex_ = ptr - rbuf_;
404 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Hash marker found at %lu.", cuid_,
405 static_cast<unsigned long>(markerIndex_)));
406 verifyReq1Hash(rbuf_ + markerIndex_);
407 // shift rbuf_
408 shiftBuffer(markerIndex_ + 20);
409 return true;
410 }
411
receiveReceiverHashAndPadCLength(const std::vector<std::shared_ptr<DownloadContext>> & downloadContexts)412 bool MSEHandshake::receiveReceiverHashAndPadCLength(
413 const std::vector<std::shared_ptr<DownloadContext>>& downloadContexts)
414 {
415 if (20 + VC_LENGTH + CRYPTO_BITFIELD_LENGTH + 2 /*PadC length*/ >
416 rbufLength_) {
417 wantRead_ = true;
418 return false;
419 }
420 // resolve info hash
421 // pointing to the position of HASH('req2', SKEY) xor HASH('req3', S)
422 unsigned char* rbufptr = rbuf_;
423 std::shared_ptr<DownloadContext> downloadContext;
424 for (auto& ctx : downloadContexts) {
425 unsigned char md[20];
426 const auto infohash = bittorrent::getInfoHash(ctx);
427 createReq23Hash(md, infohash);
428 if (memcmp(md, rbufptr, sizeof(md)) == 0) {
429 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - info hash found: %s", cuid_,
430 util::toHex(infohash, INFO_HASH_LENGTH).c_str()));
431 downloadContext = ctx;
432 break;
433 }
434 }
435 if (!downloadContext) {
436 throw DL_ABORT_EX("Unknown info hash.");
437 }
438 initCipher(bittorrent::getInfoHash(downloadContext));
439 // decrypt VC
440 rbufptr += 20;
441 verifyVC(rbufptr);
442 // decrypt crypto_provide
443 rbufptr += VC_LENGTH;
444 decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr);
445 // TODO choose the crypto type based on the preference.
446 // For now, choose ARC4.
447 if ((rbufptr[3] & CRYPTO_PLAIN_TEXT) &&
448 !option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) &&
449 option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
450 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer provides plaintext.", cuid_));
451 negotiatedCryptoType_ = CRYPTO_PLAIN_TEXT;
452 }
453 else if (rbufptr[3] & CRYPTO_ARC4) {
454 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer provides ARC4.", cuid_));
455 negotiatedCryptoType_ = CRYPTO_ARC4;
456 }
457 if (negotiatedCryptoType_ == CRYPTO_NONE) {
458 throw DL_ABORT_EX(
459 fmt("CUID#%" PRId64 " - No supported crypto type provided.", cuid_));
460 }
461 // decrypt PadC length
462 rbufptr += CRYPTO_BITFIELD_LENGTH;
463 padLength_ = verifyPadLength(rbufptr, "PadC");
464 // shift rbuf_
465 shiftBuffer(20 + VC_LENGTH + CRYPTO_BITFIELD_LENGTH + 2 /*PadC length*/);
466 return true;
467 }
468
receiveReceiverIALength()469 bool MSEHandshake::receiveReceiverIALength()
470 {
471 if (2 > rbufLength_) {
472 wantRead_ = true;
473 return false;
474 }
475 iaLength_ = decodeLength16(rbuf_);
476 if (iaLength_ > BtHandshakeMessage::MESSAGE_LENGTH) {
477 throw DL_ABORT_EX(fmt("Too large IA length length: %u", iaLength_));
478 }
479 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - len(IA)=%u.", cuid_, iaLength_));
480 // shift rbuf_
481 shiftBuffer(2);
482 return true;
483 }
484
receiveReceiverIA()485 bool MSEHandshake::receiveReceiverIA()
486 {
487 if (iaLength_ == 0) {
488 return true;
489 }
490 if (iaLength_ > rbufLength_) {
491 wantRead_ = true;
492 return false;
493 }
494 ia_ = std::vector<unsigned char>(iaLength_);
495 decryptor_->encrypt(iaLength_, ia_.data(), rbuf_);
496 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - IA received.", cuid_));
497 // shift rbuf_
498 shiftBuffer(iaLength_);
499 return true;
500 }
501
sendReceiverStep2()502 void MSEHandshake::sendReceiverStep2()
503 {
504 // buffer is filled in this order:
505 // VC(VC_LENGTH bytes),
506 // cryptoSelect(CRYPTO_BITFIELD_LENGTH bytes),
507 // len(padD)(2bytes),
508 // padD(len(padD)bytes <= MAX_PAD_LENGTH)
509 auto buffer = std::vector<unsigned char>(VC_LENGTH + CRYPTO_BITFIELD_LENGTH +
510 2 + MAX_PAD_LENGTH);
511 auto ptr = std::begin(buffer);
512 // VC
513 ptr += VC_LENGTH;
514 // crypto_select
515 ptr[3] = negotiatedCryptoType_;
516 ptr += CRYPTO_BITFIELD_LENGTH;
517 // len(padD)
518 uint16_t padDLength =
519 SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH + 1);
520 uint16_t padDLengthBE = htons(padDLength);
521 ptr = std::copy_n(reinterpret_cast<unsigned char*>(&padDLengthBE),
522 sizeof(padDLengthBE), ptr);
523 // padD, all zeroed
524 ptr += padDLength;
525 buffer.erase(ptr, std::end(buffer));
526 encryptAndSendData(std::move(buffer));
527 }
528
verifyPadLength(const unsigned char * padlenbuf,const char * padName)529 uint16_t MSEHandshake::verifyPadLength(const unsigned char* padlenbuf,
530 const char* padName)
531 {
532 A2_LOG_DEBUG(
533 fmt("CUID#%" PRId64 " - Verifying Pad length for %s", cuid_, padName));
534 uint16_t padLength = decodeLength16(padlenbuf);
535 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - len(%s)=%u", cuid_, padName, padLength));
536 if (padLength > 512) {
537 throw DL_ABORT_EX(fmt("Too large %s length: %u", padName, padLength));
538 }
539 return padLength;
540 }
541
verifyVC(unsigned char * vcbuf)542 void MSEHandshake::verifyVC(unsigned char* vcbuf)
543 {
544 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Verifying VC.", cuid_));
545 decryptor_->encrypt(VC_LENGTH, vcbuf, vcbuf);
546 if (!std::equal(std::begin(VC), std::end(VC), vcbuf)) {
547 throw DL_ABORT_EX(
548 fmt("Invalid VC: %s", util::toHex(vcbuf, VC_LENGTH).c_str()));
549 }
550 }
551
verifyReq1Hash(const unsigned char * req1buf)552 void MSEHandshake::verifyReq1Hash(const unsigned char* req1buf)
553 {
554 A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Verifying req hash.", cuid_));
555 unsigned char md[20];
556 createReq1Hash(md);
557 if (memcmp(md, req1buf, sizeof(md)) != 0) {
558 throw DL_ABORT_EX("Invalid req1 hash found.");
559 }
560 }
561
getWantWrite() const562 bool MSEHandshake::getWantWrite() const
563 {
564 return !socketBuffer_.sendBufferIsEmpty();
565 }
566
popEncryptor()567 std::unique_ptr<ARC4Encryptor> MSEHandshake::popEncryptor()
568 {
569 return std::move(encryptor_);
570 }
571
popDecryptor()572 std::unique_ptr<ARC4Encryptor> MSEHandshake::popDecryptor()
573 {
574 return std::move(decryptor_);
575 }
576
577 } // namespace aria2
578