mtproto_dc_key_creator.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "mtproto/details/mtproto_dc_key_creator.h"
  8. #include "mtproto/details/mtproto_rsa_public_key.h"
  9. #include "mtproto/connection_abstract.h"
  10. #include "mtproto/mtproto_dh_utils.h"
  11. #include "base/openssl_help.h"
  12. #include "base/random.h"
  13. #include "base/unixtime.h"
  14. #include "scheme.h"
  15. #include "logs.h"
  16. #include <cmath>
  17. namespace MTP::details {
  18. namespace {
  19. struct ParsedPQ {
  20. QByteArray p;
  21. QByteArray q;
  22. };
  23. // Fast PQ factorization taken from TDLib:
  24. // https://github.com/tdlib/td/blob/v1.7.0/tdutils/td/utils/crypto.cpp
  25. [[nodiscard]] uint64 gcd(uint64 a, uint64 b) {
  26. if (a == 0) {
  27. return b;
  28. } else if (b == 0) {
  29. return a;
  30. }
  31. int shift = 0;
  32. while ((a & 1) == 0 && (b & 1) == 0) {
  33. a >>= 1;
  34. b >>= 1;
  35. shift++;
  36. }
  37. while (true) {
  38. while ((a & 1) == 0) {
  39. a >>= 1;
  40. }
  41. while ((b & 1) == 0) {
  42. b >>= 1;
  43. }
  44. if (a > b) {
  45. a -= b;
  46. } else if (b > a) {
  47. b -= a;
  48. } else {
  49. return a << shift;
  50. }
  51. }
  52. }
  53. [[nodiscard]] uint64 FactorizeSmallPQ(uint64 pq) {
  54. if (pq < 2 || pq >(static_cast<uint64>(1) << 63)) {
  55. return 1;
  56. }
  57. uint64 g = 0;
  58. for (int i = 0, iter = 0; i < 3 || iter < 1000; i++) {
  59. uint64 q = (17 + base::RandomIndex(16)) % (pq - 1);
  60. uint64 x = base::RandomValue<uint64>() % (pq - 1) + 1;
  61. uint64 y = x;
  62. int lim = 1 << (std::min(5, i) + 18);
  63. for (int j = 1; j < lim; j++) {
  64. iter++;
  65. uint64 a = x;
  66. uint64 b = x;
  67. uint64 c = q;
  68. // c += a * b
  69. while (b) {
  70. if (b & 1) {
  71. c += a;
  72. if (c >= pq) {
  73. c -= pq;
  74. }
  75. }
  76. a += a;
  77. if (a >= pq) {
  78. a -= pq;
  79. }
  80. b >>= 1;
  81. }
  82. x = c;
  83. uint64 z = x < y ? pq + x - y : x - y;
  84. g = gcd(z, pq);
  85. if (g != 1) {
  86. break;
  87. }
  88. if (!(j & (j - 1))) {
  89. y = x;
  90. }
  91. }
  92. if (g > 1 && g < pq) {
  93. break;
  94. }
  95. }
  96. if (g != 0) {
  97. uint64 other = pq / g;
  98. if (other < g) {
  99. g = other;
  100. }
  101. }
  102. return g;
  103. }
  104. ParsedPQ FactorizeBigPQ(const QByteArray &pqStr) {
  105. using namespace openssl;
  106. Context context;
  107. BigNum a;
  108. BigNum b;
  109. BigNum p;
  110. BigNum q;
  111. auto one = BigNum(1);
  112. auto pq = BigNum(bytes::make_span(pqStr));
  113. bool found = false;
  114. for (int i = 0, iter = 0; !found && (i < 3 || iter < 1000); i++) {
  115. int32 t = 17 + base::RandomIndex(16);
  116. a.setWord(base::RandomValue<uint32>());
  117. b = a;
  118. int32 lim = 1 << (i + 23);
  119. for (int j = 1; j < lim; j++) {
  120. iter++;
  121. a.setModMul(a, a, pq, context);
  122. a.setAdd(a, BigNum(uint32(t)));
  123. if (BigNum::Compare(a, pq) >= 0) {
  124. a = BigNum::Sub(a, pq);
  125. }
  126. if (BigNum::Compare(a, b) > 0) {
  127. q.setSub(a, b);
  128. } else {
  129. q.setSub(b, a);
  130. }
  131. p.setGcd(q, pq, context);
  132. if (BigNum::Compare(p, one) != 0) {
  133. found = true;
  134. break;
  135. }
  136. if ((j & (j - 1)) == 0) {
  137. b = a;
  138. }
  139. }
  140. }
  141. if (!found) {
  142. return ParsedPQ();
  143. }
  144. BigNum::Div(&q, nullptr, pq, p, context);
  145. if (BigNum::Compare(p, q) > 0) {
  146. std::swap(p, q);
  147. }
  148. const auto pb = p.getBytes();
  149. const auto qb = q.getBytes();
  150. return {
  151. QByteArray(reinterpret_cast<const char*>(pb.data()), pb.size()),
  152. QByteArray(reinterpret_cast<const char*>(qb.data()), qb.size())
  153. };
  154. }
  155. [[nodiscard]] ParsedPQ FactorizePQ(const QByteArray &pqStr) {
  156. const auto size = pqStr.size();
  157. if (size > 8 || (size == 8 && (uchar(pqStr[0]) & 128) != 0)) {
  158. return FactorizeBigPQ(pqStr);
  159. }
  160. auto ptr = reinterpret_cast<const uchar*>(pqStr.data());
  161. uint64 pq = 0;
  162. for (auto i = 0; i != size; ++i) {
  163. pq = (pq << 8) | ptr[i];
  164. }
  165. auto p = FactorizeSmallPQ(pq);
  166. if (p == 0 || (pq % p) != 0) {
  167. return ParsedPQ();
  168. }
  169. auto q = pq / p;
  170. auto pStr = QByteArray(4, Qt::Uninitialized);
  171. uchar *pChars = (uchar*)pStr.data();
  172. for (auto i = 0; i != 4; ++i) {
  173. *(pChars + 3 - i) = (uchar)(p & 0xFF);
  174. p >>= 8;
  175. }
  176. auto qStr = QByteArray(4, Qt::Uninitialized);
  177. uchar *qChars = (uchar*)qStr.data();
  178. for (auto i = 0; i != 4; ++i) {
  179. *(qChars + 3 - i) = (uchar)(q & 0xFF);
  180. q >>= 8;
  181. }
  182. return { pStr, qStr };
  183. }
  184. [[nodiscard]] bool IsGoodEncryptedInner(
  185. bytes::const_span keyAesEncrypted,
  186. const RSAPublicKey &key) {
  187. Expects(keyAesEncrypted.size() == 256);
  188. const auto modulus = key.getN();
  189. const auto e = key.getE();
  190. const auto shift = (256 - int(modulus.size()));
  191. Assert(shift >= 0);
  192. for (auto i = 0; i != 256; ++i) {
  193. const auto a = keyAesEncrypted[i];
  194. const auto b = (i < shift)
  195. ? bytes::type(0)
  196. : modulus[i - shift];
  197. if (a > b) {
  198. return false;
  199. } else if (a < b) {
  200. return true;
  201. }
  202. }
  203. return false;
  204. }
  205. template <typename PQInnerData>
  206. [[nodiscard]] bytes::vector EncryptPQInnerRSA(
  207. const PQInnerData &data,
  208. const RSAPublicKey &key) {
  209. DEBUG_LOG(("AuthKey Info: encrypting pq inner..."));
  210. constexpr auto kPrime = sizeof(mtpPrime);
  211. constexpr auto kDataWithPaddingPrimes = 192 / kPrime;
  212. constexpr auto kMaxSizeInPrimes = 144 / kPrime;
  213. constexpr auto kDataHashPrimes = (SHA256_DIGEST_LENGTH / kPrime);
  214. constexpr auto kKeySize = 32;
  215. constexpr auto kIvSize = 32;
  216. using BoxedPQInnerData = std::conditional_t<
  217. tl::is_boxed_v<PQInnerData>,
  218. PQInnerData,
  219. tl::boxed<PQInnerData>>;
  220. const auto boxed = BoxedPQInnerData(data);
  221. const auto p_q_inner_size = tl::count_length(boxed);
  222. const auto sizeInPrimes = (p_q_inner_size / kPrime);
  223. if (sizeInPrimes > kMaxSizeInPrimes) {
  224. return {};
  225. }
  226. auto dataWithPadding = mtpBuffer();
  227. dataWithPadding.reserve(kDataWithPaddingPrimes);
  228. boxed.write(dataWithPadding);
  229. // data_with_padding := data + random_padding_bytes;
  230. dataWithPadding.resize(kDataWithPaddingPrimes);
  231. const auto dataWithPaddingBytes = bytes::make_span(dataWithPadding);
  232. bytes::set_random(dataWithPaddingBytes.subspan(sizeInPrimes * kPrime));
  233. DEBUG_LOG(("AuthKey Info: starting key generation for pq inner..."));
  234. while (true) {
  235. auto dataWithHash = mtpBuffer();
  236. dataWithHash.reserve(kDataWithPaddingPrimes + kDataHashPrimes);
  237. dataWithHash.append(dataWithPadding);
  238. // data_pad_reversed := BYTE_REVERSE(data_with_padding);
  239. ranges::reverse(bytes::make_span(dataWithHash));
  240. // data_with_hash := data_pad_reversed
  241. // + SHA256(temp_key + data_with_padding);
  242. const auto tempKey = base::RandomValue<bytes::array<kKeySize>>();
  243. dataWithHash.resize(kDataWithPaddingPrimes + kDataHashPrimes);
  244. const auto dataWithHashBytes = bytes::make_span(dataWithHash);
  245. bytes::copy(
  246. dataWithHashBytes.subspan(kDataWithPaddingPrimes * kPrime),
  247. openssl::Sha256(tempKey, bytes::make_span(dataWithPadding)));
  248. auto aesEncrypted = mtpBuffer();
  249. auto keyAesEncrypted = mtpBuffer();
  250. aesEncrypted.resize(dataWithHash.size());
  251. const auto aesEncryptedBytes = bytes::make_span(aesEncrypted);
  252. DEBUG_LOG(("AuthKey Info: encrypting ige for pq inner..."));
  253. // aes_encrypted := AES256_IGE(data_with_hash, temp_key, 0);
  254. const auto tempIv = bytes::array<kIvSize>{ { bytes::type(0) } };
  255. aesIgeEncryptRaw(
  256. dataWithHashBytes.data(),
  257. aesEncryptedBytes.data(),
  258. dataWithHashBytes.size(),
  259. tempKey.data(),
  260. tempIv.data());
  261. DEBUG_LOG(("AuthKey Info: counting hash for pq inner..."));
  262. // temp_key_xor := temp_key XOR SHA256(aes_encrypted);
  263. const auto fullSize = (kKeySize / kPrime) + dataWithHash.size();
  264. keyAesEncrypted.resize(fullSize);
  265. const auto keyAesEncryptedBytes = bytes::make_span(keyAesEncrypted);
  266. const auto aesHash = openssl::Sha256(aesEncryptedBytes);
  267. for (auto i = 0; i != kKeySize; ++i) {
  268. keyAesEncryptedBytes[i] = tempKey[i] ^ aesHash[i];
  269. }
  270. DEBUG_LOG(("AuthKey Info: checking chosen key for pq inner..."));
  271. // key_aes_encrypted := temp_key_xor + aes_encrypted;
  272. bytes::copy(
  273. keyAesEncryptedBytes.subspan(kKeySize),
  274. aesEncryptedBytes);
  275. if (IsGoodEncryptedInner(keyAesEncryptedBytes, key)) {
  276. DEBUG_LOG(("AuthKey Info: chosen key for pq inner is good."));
  277. return key.encrypt(keyAesEncryptedBytes);
  278. }
  279. DEBUG_LOG(("AuthKey Info: chosen key for pq inner is bad..."));
  280. }
  281. }
  282. [[nodiscard]] std::string EncryptClientDHInner(
  283. const MTPClient_DH_Inner_Data &data,
  284. const void *aesKey,
  285. const void *aesIV) {
  286. constexpr auto kSkipPrimes = openssl::kSha1Size / sizeof(mtpPrime);
  287. auto client_dh_inner_size = tl::count_length(data);
  288. auto encSize = (client_dh_inner_size >> 2) + kSkipPrimes;
  289. auto encFullSize = encSize;
  290. if (encSize & 0x03) {
  291. encFullSize += 4 - (encSize & 0x03);
  292. }
  293. auto encBuffer = mtpBuffer();
  294. encBuffer.reserve(encFullSize);
  295. encBuffer.resize(kSkipPrimes);
  296. data.write(encBuffer);
  297. encBuffer.resize(encFullSize);
  298. const auto bytes = bytes::make_span(encBuffer);
  299. const auto hash = openssl::Sha1(bytes.subspan(
  300. kSkipPrimes * sizeof(mtpPrime),
  301. client_dh_inner_size));
  302. bytes::copy(bytes, hash);
  303. bytes::set_random(bytes.subspan(encSize * sizeof(mtpPrime)));
  304. auto sdhEncString = std::string(encFullSize * 4, ' ');
  305. aesIgeEncryptRaw(&encBuffer[0], &sdhEncString[0], encFullSize * sizeof(mtpPrime), aesKey, aesIV);
  306. return sdhEncString;
  307. }
  308. // 128 lower-order bits of SHA1.
  309. MTPint128 NonceDigest(bytes::const_span data) {
  310. const auto hash = openssl::Sha1(data);
  311. return *(MTPint128*)(hash.data() + 4);
  312. }
  313. } // namespace
  314. DcKeyCreator::Attempt::~Attempt() {
  315. const auto clearBytes = [](bytes::span bytes) {
  316. OPENSSL_cleanse(bytes.data(), bytes.size());
  317. };
  318. OPENSSL_cleanse(&data, sizeof(data));
  319. clearBytes(dhPrime);
  320. clearBytes(g_a);
  321. clearBytes(authKey);
  322. }
  323. DcKeyCreator::DcKeyCreator(
  324. DcId dcId,
  325. int16 protocolDcId,
  326. not_null<AbstractConnection*> connection,
  327. not_null<DcOptions*> dcOptions,
  328. Delegate delegate,
  329. DcKeyRequest request)
  330. : _connection(connection)
  331. , _dcOptions(dcOptions)
  332. , _dcId(dcId)
  333. , _protocolDcId(protocolDcId)
  334. , _request(request)
  335. , _delegate(std::move(delegate)) {
  336. Expects(_request.temporaryExpiresIn > 0);
  337. Expects(_delegate.done != nullptr);
  338. QObject::connect(_connection, &AbstractConnection::receivedData, [=] {
  339. answered();
  340. });
  341. if (_request.persistentNeeded) {
  342. pqSend(&_persistent, 0);
  343. } else {
  344. pqSend(&_temporary, _request.temporaryExpiresIn);
  345. }
  346. }
  347. DcKeyCreator::~DcKeyCreator() {
  348. if (_delegate.done) {
  349. stopReceiving();
  350. }
  351. }
  352. template <typename RequestType>
  353. void DcKeyCreator::sendNotSecureRequest(const RequestType &request) {
  354. auto packet = _connection->prepareNotSecurePacket(
  355. request,
  356. base::unixtime::mtproto_msg_id());
  357. DEBUG_LOG(("AuthKey Info: sending request, size: %1, time: %3"
  358. ).arg(packet.size() - 8
  359. ).arg(packet[5]));
  360. const auto bytesSize = packet.size() * sizeof(mtpPrime);
  361. _connection->sendData(std::move(packet));
  362. if (_delegate.sentSome) {
  363. _delegate.sentSome(bytesSize);
  364. }
  365. }
  366. template <typename RequestType, typename Response>
  367. std::optional<Response> DcKeyCreator::readNotSecureResponse(
  368. gsl::span<const mtpPrime> answer) {
  369. auto from = answer.data();
  370. auto result = Response();
  371. if (result.read(from, from + answer.size())) {
  372. return result;
  373. }
  374. return std::nullopt;
  375. }
  376. void DcKeyCreator::answered() {
  377. if (_delegate.receivedSome) {
  378. _delegate.receivedSome();
  379. }
  380. if (_connection->received().empty()) {
  381. LOG(("AuthKey Error: "
  382. "trying to read response from empty received list"));
  383. return failed();
  384. }
  385. const auto buffer = std::move(_connection->received().front());
  386. _connection->received().pop_front();
  387. const auto answer = _connection->parseNotSecureResponse(buffer);
  388. if (answer.empty()) {
  389. return failed();
  390. }
  391. handleAnswer(answer);
  392. }
  393. DcKeyCreator::Attempt *DcKeyCreator::attemptByNonce(const MTPint128 &nonce) {
  394. if (_temporary.data.nonce == nonce) {
  395. DEBUG_LOG(("AuthKey Info: receiving answer for temporary..."));
  396. return &_temporary;
  397. } else if (_persistent.data.nonce == nonce) {
  398. DEBUG_LOG(("AuthKey Info: receiving answer for persistent..."));
  399. return &_persistent;
  400. }
  401. LOG(("AuthKey Error: attempt by nonce not found."));
  402. return nullptr;
  403. }
  404. void DcKeyCreator::handleAnswer(gsl::span<const mtpPrime> answer) {
  405. if (const auto resPQ = readNotSecureResponse<MTPReq_pq>(answer)) {
  406. const auto nonce = resPQ->match([](const auto &data) {
  407. return data.vnonce();
  408. });
  409. if (const auto attempt = attemptByNonce(nonce)) {
  410. DEBUG_LOG(("AuthKey Info: receiving Req_pq answer..."));
  411. return pqAnswered(attempt, *resPQ);
  412. }
  413. } else if (const auto resDH = readNotSecureResponse<MTPReq_DH_params>(answer)) {
  414. const auto nonce = resDH->match([](const auto &data) {
  415. return data.vnonce();
  416. });
  417. if (const auto attempt = attemptByNonce(nonce)) {
  418. DEBUG_LOG(("AuthKey Info: receiving Req_DH_params answer..."));
  419. return dhParamsAnswered(attempt, *resDH);
  420. }
  421. } else if (const auto result = readNotSecureResponse<MTPSet_client_DH_params>(answer)) {
  422. const auto nonce = result->match([](const auto &data) {
  423. return data.vnonce();
  424. });
  425. if (const auto attempt = attemptByNonce(nonce)) {
  426. DEBUG_LOG(("AuthKey Info: receiving Req_client_DH_params answer..."));
  427. return dhClientParamsAnswered(attempt, *result);
  428. }
  429. }
  430. LOG(("AuthKey Error: Unknown answer received."));
  431. failed();
  432. }
  433. void DcKeyCreator::pqSend(not_null<Attempt*> attempt, TimeId expiresIn) {
  434. DEBUG_LOG(("AuthKey Info: sending Req_pq for %1..."
  435. ).arg(expiresIn ? "temporary" : "persistent"));
  436. attempt->stage = Stage::WaitingPQ;
  437. attempt->expiresIn = expiresIn;
  438. attempt->data.nonce = base::RandomValue<MTPint128>();
  439. sendNotSecureRequest(MTPReq_pq_multi(attempt->data.nonce));
  440. }
  441. void DcKeyCreator::pqAnswered(
  442. not_null<Attempt*> attempt,
  443. const MTPresPQ &data) {
  444. data.match([&](const MTPDresPQ &data) {
  445. Expects(data.vnonce() == attempt->data.nonce);
  446. if (attempt->stage != Stage::WaitingPQ) {
  447. LOG(("AuthKey Error: Unexpected stage %1").arg(int(attempt->stage)));
  448. return failed();
  449. }
  450. DEBUG_LOG(("AuthKey Info: getting dc RSA key..."));
  451. const auto rsaKey = _dcOptions->getDcRSAKey(
  452. _dcId,
  453. data.vserver_public_key_fingerprints().v);
  454. if (!rsaKey.valid()) {
  455. DEBUG_LOG(("AuthKey Error: unknown public key."));
  456. return failed(DcKeyError::UnknownPublicKey);
  457. }
  458. attempt->data.server_nonce = data.vserver_nonce();
  459. attempt->data.new_nonce = base::RandomValue<MTPint256>();
  460. DEBUG_LOG(("AuthKey Info: parsing pq..."));
  461. const auto &pq = data.vpq().v;
  462. const auto parsed = FactorizePQ(data.vpq().v);
  463. if (parsed.p.isEmpty() || parsed.q.isEmpty()) {
  464. LOG(("AuthKey Error: could not factor pq!"));
  465. DEBUG_LOG(("AuthKey Error: problematic pq: %1").arg(Logs::mb(pq.constData(), pq.length()).str()));
  466. return failed();
  467. }
  468. DEBUG_LOG(("AuthKey Info: parse pq done."));
  469. const auto dhEncString = [&] {
  470. return (attempt->expiresIn == 0)
  471. ? EncryptPQInnerRSA(
  472. MTP_p_q_inner_data_dc(
  473. data.vpq(),
  474. MTP_bytes(parsed.p),
  475. MTP_bytes(parsed.q),
  476. attempt->data.nonce,
  477. attempt->data.server_nonce,
  478. attempt->data.new_nonce,
  479. MTP_int(_protocolDcId)),
  480. rsaKey)
  481. : EncryptPQInnerRSA(
  482. MTP_p_q_inner_data_temp_dc(
  483. data.vpq(),
  484. MTP_bytes(parsed.p),
  485. MTP_bytes(parsed.q),
  486. attempt->data.nonce,
  487. attempt->data.server_nonce,
  488. attempt->data.new_nonce,
  489. MTP_int(_protocolDcId),
  490. MTP_int(attempt->expiresIn)),
  491. rsaKey);
  492. }();
  493. if (dhEncString.empty()) {
  494. DEBUG_LOG(("AuthKey Error: could not encrypt pq inner."));
  495. return failed();
  496. }
  497. attempt->stage = Stage::WaitingDH;
  498. DEBUG_LOG(("AuthKey Info: sending Req_DH_params..."));
  499. sendNotSecureRequest(MTPReq_DH_params(
  500. attempt->data.nonce,
  501. attempt->data.server_nonce,
  502. MTP_bytes(parsed.p),
  503. MTP_bytes(parsed.q),
  504. MTP_long(rsaKey.fingerprint()),
  505. MTP_bytes(dhEncString)));
  506. });
  507. }
  508. void DcKeyCreator::dhParamsAnswered(
  509. not_null<Attempt*> attempt,
  510. const MTPserver_DH_Params &data) {
  511. if (attempt->stage != Stage::WaitingDH) {
  512. LOG(("AuthKey Error: Unexpected stage %1").arg(int(attempt->stage)));
  513. return failed();
  514. }
  515. data.match([&](const MTPDserver_DH_params_ok &data) {
  516. Expects(data.vnonce() == attempt->data.nonce);
  517. if (data.vserver_nonce() != attempt->data.server_nonce) {
  518. LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in server_DH_params_ok)!"));
  519. DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(Logs::mb(&data.vserver_nonce(), 16).str(), Logs::mb(&attempt->data.server_nonce, 16).str()));
  520. return failed();
  521. }
  522. auto &encDHStr = data.vencrypted_answer().v;
  523. uint32 encDHLen = encDHStr.length(), encDHBufLen = encDHLen >> 2;
  524. if ((encDHLen & 0x03) || encDHBufLen < 6) {
  525. LOG(("AuthKey Error: bad encrypted data length %1 (in server_DH_params_ok)!").arg(encDHLen));
  526. DEBUG_LOG(("AuthKey Error: received encrypted data %1").arg(Logs::mb(encDHStr.constData(), encDHLen).str()));
  527. return failed();
  528. }
  529. const auto nlen = sizeof(attempt->data.new_nonce);
  530. const auto slen = sizeof(attempt->data.server_nonce);
  531. auto tmp_aes_buffer = bytes::array<1024>();
  532. const auto tmp_aes = bytes::make_span(tmp_aes_buffer);
  533. bytes::copy(tmp_aes, bytes::object_as_span(&attempt->data.new_nonce));
  534. bytes::copy(tmp_aes.subspan(nlen), bytes::object_as_span(&attempt->data.server_nonce));
  535. bytes::copy(tmp_aes.subspan(nlen + slen), bytes::object_as_span(&attempt->data.new_nonce));
  536. bytes::copy(tmp_aes.subspan(nlen + slen + nlen), bytes::object_as_span(&attempt->data.new_nonce));
  537. const auto sha1ns = openssl::Sha1(tmp_aes.subspan(0, nlen + slen));
  538. const auto sha1sn = openssl::Sha1(tmp_aes.subspan(nlen, nlen + slen));
  539. const auto sha1nn = openssl::Sha1(tmp_aes.subspan(nlen + slen, nlen + nlen));
  540. mtpBuffer decBuffer;
  541. decBuffer.resize(encDHBufLen);
  542. const auto aesKey = bytes::make_span(attempt->data.aesKey);
  543. const auto aesIV = bytes::make_span(attempt->data.aesIV);
  544. bytes::copy(aesKey, bytes::make_span(sha1ns).subspan(0, 20));
  545. bytes::copy(aesKey.subspan(20), bytes::make_span(sha1sn).subspan(0, 12));
  546. bytes::copy(aesIV, bytes::make_span(sha1sn).subspan(12, 8));
  547. bytes::copy(aesIV.subspan(8), bytes::make_span(sha1nn).subspan(0, 20));
  548. bytes::copy(aesIV.subspan(28), bytes::object_as_span(&attempt->data.new_nonce).subspan(0, 4));
  549. aesIgeDecryptRaw(encDHStr.constData(), &decBuffer[0], encDHLen, aesKey.data(), aesIV.data());
  550. const mtpPrime *from(&decBuffer[5]), *to(from), *end(from + (encDHBufLen - 5));
  551. MTPServer_DH_inner_data dh_inner;
  552. if (!dh_inner.read(to, end)) {
  553. LOG(("AuthKey Error: could not decrypt server_DH_inner_data!"));
  554. return failed();
  555. }
  556. const auto &dh_inner_data(dh_inner.c_server_DH_inner_data());
  557. if (dh_inner_data.vnonce() != attempt->data.nonce) {
  558. LOG(("AuthKey Error: received nonce <> sent nonce (in server_DH_inner_data)!"));
  559. DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(Logs::mb(&dh_inner_data.vnonce(), 16).str(), Logs::mb(&attempt->data.nonce, 16).str()));
  560. return failed();
  561. }
  562. if (dh_inner_data.vserver_nonce() != attempt->data.server_nonce) {
  563. LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in server_DH_inner_data)!"));
  564. DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(Logs::mb(&dh_inner_data.vserver_nonce(), 16).str(), Logs::mb(&attempt->data.server_nonce, 16).str()));
  565. return failed();
  566. }
  567. const auto sha1Buffer = openssl::Sha1(
  568. bytes::make_span(decBuffer).subspan(
  569. 5 * sizeof(mtpPrime),
  570. (to - from) * sizeof(mtpPrime)));
  571. const auto sha1Dec = bytes::make_span(decBuffer).subspan(
  572. 0,
  573. openssl::kSha1Size);
  574. if (bytes::compare(sha1Dec, sha1Buffer)) {
  575. LOG(("AuthKey Error: sha1 hash of encrypted part did not match!"));
  576. DEBUG_LOG(("AuthKey Error: sha1 did not match, server_nonce: %1, new_nonce %2, encrypted data %3").arg(Logs::mb(&attempt->data.server_nonce, 16).str(), Logs::mb(&attempt->data.new_nonce, 16).str(), Logs::mb(encDHStr.constData(), encDHLen).str()));
  577. return failed();
  578. }
  579. base::unixtime::update(dh_inner_data.vserver_time().v);
  580. // check that dhPrime and (dhPrime - 1) / 2 are really prime
  581. if (!IsPrimeAndGood(bytes::make_span(dh_inner_data.vdh_prime().v), dh_inner_data.vg().v)) {
  582. LOG(("AuthKey Error: bad dh_prime primality!"));
  583. return failed();
  584. }
  585. attempt->dhPrime = bytes::make_vector(
  586. dh_inner_data.vdh_prime().v);
  587. attempt->data.g = dh_inner_data.vg().v;
  588. attempt->g_a = bytes::make_vector(dh_inner_data.vg_a().v);
  589. attempt->data.retry_id = MTP_long(0);
  590. attempt->retries = 0;
  591. dhClientParamsSend(attempt);
  592. }, [&](const MTPDserver_DH_params_fail &data) {
  593. Expects(data.vnonce() == attempt->data.nonce);
  594. if (data.vserver_nonce() != attempt->data.server_nonce) {
  595. LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in server_DH_params_fail)!"));
  596. DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(Logs::mb(&data.vserver_nonce(), 16).str(), Logs::mb(&attempt->data.server_nonce, 16).str()));
  597. return failed();
  598. }
  599. if (data.vnew_nonce_hash() != NonceDigest(bytes::object_as_span(&attempt->data.new_nonce))) {
  600. LOG(("AuthKey Error: received new_nonce_hash did not match!"));
  601. DEBUG_LOG(("AuthKey Error: received new_nonce_hash: %1, new_nonce: %2").arg(Logs::mb(&data.vnew_nonce_hash(), 16).str(), Logs::mb(&attempt->data.new_nonce, 32).str()));
  602. return failed();
  603. }
  604. LOG(("AuthKey Error: server_DH_params_fail received!"));
  605. failed();
  606. });
  607. }
  608. void DcKeyCreator::dhClientParamsSend(not_null<Attempt*> attempt) {
  609. if (++attempt->retries > 5) {
  610. LOG(("AuthKey Error: could not create auth_key for %1 retries").arg(attempt->retries - 1));
  611. return failed();
  612. }
  613. // gen rand 'b'
  614. auto randomSeed = bytes::vector(ModExpFirst::kRandomPowerSize);
  615. bytes::set_random(randomSeed);
  616. auto g_b_data = CreateModExp(attempt->data.g, attempt->dhPrime, randomSeed);
  617. if (g_b_data.modexp.empty()) {
  618. LOG(("AuthKey Error: could not generate good g_b."));
  619. return failed();
  620. }
  621. auto computedAuthKey = CreateAuthKey(attempt->g_a, g_b_data.randomPower, attempt->dhPrime);
  622. if (computedAuthKey.empty()) {
  623. LOG(("AuthKey Error: could not generate auth_key."));
  624. return failed();
  625. }
  626. AuthKey::FillData(attempt->authKey, computedAuthKey);
  627. auto auth_key_sha = openssl::Sha1(attempt->authKey);
  628. memcpy(&attempt->data.auth_key_aux_hash.v, auth_key_sha.data(), 8);
  629. memcpy(&attempt->data.auth_key_hash.v, auth_key_sha.data() + 12, 8);
  630. const auto client_dh_inner = MTP_client_DH_inner_data(
  631. attempt->data.nonce,
  632. attempt->data.server_nonce,
  633. attempt->data.retry_id,
  634. MTP_bytes(g_b_data.modexp));
  635. auto sdhEncString = EncryptClientDHInner(
  636. client_dh_inner,
  637. attempt->data.aesKey.data(),
  638. attempt->data.aesIV.data());
  639. attempt->stage = Stage::WaitingDone;
  640. DEBUG_LOG(("AuthKey Info: sending Req_client_DH_params..."));
  641. sendNotSecureRequest(MTPSet_client_DH_params(
  642. attempt->data.nonce,
  643. attempt->data.server_nonce,
  644. MTP_string(std::move(sdhEncString))));
  645. }
  646. void DcKeyCreator::dhClientParamsAnswered(
  647. not_null<Attempt*> attempt,
  648. const MTPset_client_DH_params_answer &data) {
  649. if (attempt->stage != Stage::WaitingDone) {
  650. LOG(("AuthKey Error: Unexpected stage %1").arg(int(attempt->stage)));
  651. return failed();
  652. }
  653. data.match([&](const MTPDdh_gen_ok &data) {
  654. if (data.vnonce() != attempt->data.nonce) {
  655. LOG(("AuthKey Error: received nonce <> sent nonce (in dh_gen_ok)!"));
  656. DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(Logs::mb(&data.vnonce(), 16).str(), Logs::mb(&attempt->data.nonce, 16).str()));
  657. return failed();
  658. }
  659. if (data.vserver_nonce() != attempt->data.server_nonce) {
  660. LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_ok)!"));
  661. DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(Logs::mb(&data.vserver_nonce(), 16).str(), Logs::mb(&attempt->data.server_nonce, 16).str()));
  662. return failed();
  663. }
  664. attempt->data.new_nonce_buf[32] = bytes::type(1);
  665. if (data.vnew_nonce_hash1() != NonceDigest(attempt->data.new_nonce_buf)) {
  666. LOG(("AuthKey Error: received new_nonce_hash1 did not match!"));
  667. DEBUG_LOG(("AuthKey Error: received new_nonce_hash1: %1, new_nonce_buf: %2").arg(Logs::mb(&data.vnew_nonce_hash1(), 16).str(), Logs::mb(attempt->data.new_nonce_buf.data(), 41).str()));
  668. return failed();
  669. }
  670. uint64 salt1 = attempt->data.new_nonce.l.l, salt2 = attempt->data.server_nonce.l;
  671. attempt->data.doneSalt = salt1 ^ salt2;
  672. attempt->stage = Stage::Ready;
  673. done();
  674. }, [&](const MTPDdh_gen_retry &data) {
  675. if (data.vnonce() != attempt->data.nonce) {
  676. LOG(("AuthKey Error: received nonce <> sent nonce (in dh_gen_retry)!"));
  677. DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(Logs::mb(&data.vnonce(), 16).str(), Logs::mb(&attempt->data.nonce, 16).str()));
  678. return failed();
  679. }
  680. if (data.vserver_nonce() != attempt->data.server_nonce) {
  681. LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_retry)!"));
  682. DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(Logs::mb(&data.vserver_nonce(), 16).str(), Logs::mb(&attempt->data.server_nonce, 16).str()));
  683. return failed();
  684. }
  685. attempt->data.new_nonce_buf[32] = bytes::type(2);
  686. if (data.vnew_nonce_hash2() != NonceDigest(attempt->data.new_nonce_buf)) {
  687. LOG(("AuthKey Error: received new_nonce_hash2 did not match!"));
  688. DEBUG_LOG(("AuthKey Error: received new_nonce_hash2: %1, new_nonce_buf: %2").arg(Logs::mb(&data.vnew_nonce_hash2(), 16).str(), Logs::mb(attempt->data.new_nonce_buf.data(), 41).str()));
  689. return failed();
  690. }
  691. attempt->data.retry_id = attempt->data.auth_key_aux_hash;
  692. dhClientParamsSend(attempt);
  693. }, [&](const MTPDdh_gen_fail &data) {
  694. if (data.vnonce() != attempt->data.nonce) {
  695. LOG(("AuthKey Error: received nonce <> sent nonce (in dh_gen_fail)!"));
  696. DEBUG_LOG(("AuthKey Error: received nonce: %1, sent nonce: %2").arg(Logs::mb(&data.vnonce(), 16).str(), Logs::mb(&attempt->data.nonce, 16).str()));
  697. return failed();
  698. }
  699. if (data.vserver_nonce() != attempt->data.server_nonce) {
  700. LOG(("AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_fail)!"));
  701. DEBUG_LOG(("AuthKey Error: received server_nonce: %1, sent server_nonce: %2").arg(Logs::mb(&data.vserver_nonce(), 16).str(), Logs::mb(&attempt->data.server_nonce, 16).str()));
  702. return failed();
  703. }
  704. attempt->data.new_nonce_buf[32] = bytes::type(3);
  705. if (data.vnew_nonce_hash3() != NonceDigest(attempt->data.new_nonce_buf)) {
  706. LOG(("AuthKey Error: received new_nonce_hash3 did not match!"));
  707. DEBUG_LOG(("AuthKey Error: received new_nonce_hash3: %1, new_nonce_buf: %2").arg(Logs::mb(&data.vnew_nonce_hash3(), 16).str(), Logs::mb(attempt->data.new_nonce_buf.data(), 41).str()));
  708. return failed();
  709. }
  710. LOG(("AuthKey Error: dh_gen_fail received!"));
  711. failed();
  712. });
  713. }
  714. void DcKeyCreator::failed(DcKeyError error) {
  715. stopReceiving();
  716. auto onstack = base::take(_delegate.done);
  717. onstack(tl::unexpected(error));
  718. }
  719. void DcKeyCreator::done() {
  720. if (_temporary.stage == Stage::None) {
  721. pqSend(&_temporary, _request.temporaryExpiresIn);
  722. return;
  723. }
  724. Assert(_temporary.stage == Stage::Ready);
  725. Assert(_persistent.stage == Stage::Ready || _persistent.stage == Stage::None);
  726. auto result = DcKeyResult();
  727. result.temporaryKey = std::make_shared<AuthKey>(
  728. AuthKey::Type::Temporary,
  729. _dcId,
  730. _temporary.authKey);
  731. result.temporaryServerSalt = _temporary.data.doneSalt;
  732. if (_persistent.stage == Stage::Ready) {
  733. result.persistentKey = std::make_shared<AuthKey>(
  734. AuthKey::Type::Generated,
  735. _dcId,
  736. _persistent.authKey);
  737. result.persistentServerSalt = _persistent.data.doneSalt;
  738. }
  739. stopReceiving();
  740. auto onstack = base::take(_delegate.done);
  741. onstack(std::move(result));
  742. }
  743. void DcKeyCreator::stopReceiving() {
  744. QObject::disconnect(
  745. _connection,
  746. &AbstractConnection::receivedData,
  747. nullptr,
  748. nullptr);
  749. }
  750. } // namespace MTP::details