/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "mtproto/core_types.h" #include "mtproto/mtproto_auth_key.h" #include "mtproto/connection_abstract.h" #include "base/basic_types.h" #include "base/expected.h" namespace MTP { class DcOptions; } // namespace MTP namespace MTP::details { struct DcKeyRequest { TimeId temporaryExpiresIn = 0; bool persistentNeeded = false; }; enum class DcKeyError { UnknownPublicKey, Other, }; struct DcKeyResult { AuthKeyPtr persistentKey; AuthKeyPtr temporaryKey; uint64 temporaryServerSalt = 0; uint64 persistentServerSalt = 0; }; class DcKeyCreator final { public: struct Delegate { Fn)> done; Fn sentSome; Fn receivedSome; }; DcKeyCreator( DcId dcId, int16 protocolDcId, not_null connection, not_null dcOptions, Delegate delegate, DcKeyRequest request); ~DcKeyCreator(); private: enum class Stage { None, WaitingPQ, WaitingDH, WaitingDone, Ready, }; struct Data { Data() : new_nonce(*(MTPint256*)((uchar*)new_nonce_buf.data())) , auth_key_aux_hash(*(MTPlong*)((uchar*)new_nonce_buf.data() + 33)) { } MTPint128 nonce, server_nonce; // 32 bytes new_nonce + 1 check byte + 8 bytes of auth_key_aux_hash. bytes::array<41> new_nonce_buf; MTPint256 &new_nonce; MTPlong &auth_key_aux_hash; MTPlong retry_id; int32 g = 0; bytes::array<32> aesKey; bytes::array<32> aesIV; MTPlong auth_key_hash; uint64 doneSalt = 0; }; struct Attempt { ~Attempt(); Data data; bytes::vector dhPrime; bytes::vector g_a; AuthKey::Data authKey = { { gsl::byte{} } }; TimeId expiresIn = 0; uint32 retries = 0; Stage stage = Stage::None; }; template void sendNotSecureRequest(const RequestType &request); template < typename RequestType, typename Response = typename RequestType::ResponseType> [[nodiscard]] std::optional readNotSecureResponse( gsl::span answer); Attempt *attemptByNonce(const MTPint128 &nonce); void answered(); void handleAnswer(gsl::span answer); void pqSend(not_null attempt, TimeId expiresIn); void pqAnswered( not_null attempt, const MTPresPQ &data); void dhParamsAnswered( not_null attempt, const MTPserver_DH_Params &data); void dhClientParamsSend(not_null attempt); void dhClientParamsAnswered( not_null attempt, const MTPset_client_DH_params_answer &data); void stopReceiving(); void failed(DcKeyError error = DcKeyError::Other); void done(); const not_null _connection; const not_null _dcOptions; const DcId _dcId = 0; const int16 _protocolDcId = 0; const DcKeyRequest _request; Delegate _delegate; Attempt _temporary; Attempt _persistent; }; } // namespace MTP::details