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