2019-11-13 17:12:04 +03:00
/*
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
*/
# include "mtproto/details/mtproto_dc_key_creator.h"
2019-12-02 16:10:19 +03:00
# include "mtproto/details/mtproto_rsa_public_key.h"
2019-11-13 17:12:04 +03:00
# include "mtproto/connection_abstract.h"
# include "mtproto/mtproto_dh_utils.h"
# include "base/openssl_help.h"
2021-09-15 13:21:45 +03:00
# include "base/random.h"
2019-11-13 17:12:04 +03:00
# include "base/unixtime.h"
# include "scheme.h"
# include "logs.h"
2019-11-15 17:11:05 +03:00
# include <cmath>
2019-11-13 17:12:04 +03:00
namespace MTP : : details {
namespace {
struct ParsedPQ {
QByteArray p ;
QByteArray q ;
} ;
2021-09-30 21:13:34 +04:00
// Fast PQ factorization taken from TDLib:
// https://github.com/tdlib/td/blob/v1.7.0/tdutils/td/utils/crypto.cpp
[[nodiscard]] uint64 gcd ( uint64 a , uint64 b ) {
if ( a = = 0 ) {
return b ;
} else if ( b = = 0 ) {
return a ;
2019-11-13 17:12:04 +03:00
}
2021-09-30 21:13:34 +04:00
int shift = 0 ;
while ( ( a & 1 ) = = 0 & & ( b & 1 ) = = 0 ) {
a > > = 1 ;
b > > = 1 ;
shift + + ;
2019-11-13 17:12:04 +03:00
}
2021-09-30 21:13:34 +04:00
while ( true ) {
while ( ( a & 1 ) = = 0 ) {
a > > = 1 ;
2019-11-13 17:12:04 +03:00
}
2021-09-30 21:13:34 +04:00
while ( ( b & 1 ) = = 0 ) {
b > > = 1 ;
}
if ( a > b ) {
a - = b ;
} else if ( b > a ) {
b - = a ;
} else {
return a < < shift ;
}
}
}
[[nodiscard]] uint64 FactorizeSmallPQ ( uint64 pq ) {
if ( pq < 2 | | pq > ( static_cast < uint64 > ( 1 ) < < 63 ) ) {
return 1 ;
}
uint64 g = 0 ;
for ( int i = 0 , iter = 0 ; i < 3 | | iter < 1000 ; i + + ) {
uint64 q = ( 17 + base : : RandomIndex ( 16 ) ) % ( pq - 1 ) ;
uint64 x = base : : RandomValue < uint64 > ( ) % ( pq - 1 ) + 1 ;
uint64 y = x ;
int lim = 1 < < ( std : : min ( 5 , i ) + 18 ) ;
for ( int j = 1 ; j < lim ; j + + ) {
iter + + ;
uint64 a = x ;
uint64 b = x ;
uint64 c = q ;
// c += a * b
while ( b ) {
if ( b & 1 ) {
c + = a ;
if ( c > = pq ) {
c - = pq ;
}
}
a + = a ;
if ( a > = pq ) {
a - = pq ;
}
b > > = 1 ;
}
x = c ;
uint64 z = x < y ? pq + x - y : x - y ;
g = gcd ( z , pq ) ;
if ( g ! = 1 ) {
break ;
}
if ( ! ( j & ( j - 1 ) ) ) {
y = x ;
}
}
if ( g > 1 & & g < pq ) {
2019-11-13 17:12:04 +03:00
break ;
}
}
2021-09-30 21:13:34 +04:00
if ( g ! = 0 ) {
uint64 other = pq / g ;
if ( other < g ) {
g = other ;
}
}
return g ;
}
ParsedPQ FactorizeBigPQ ( const QByteArray & pqStr ) {
using namespace openssl ;
Context context ;
BigNum a ;
BigNum b ;
BigNum p ;
BigNum q ;
auto one = BigNum ( 1 ) ;
auto pq = BigNum ( bytes : : make_span ( pqStr ) ) ;
bool found = false ;
for ( int i = 0 , iter = 0 ; ! found & & ( i < 3 | | iter < 1000 ) ; i + + ) {
int32 t = 17 + base : : RandomIndex ( 16 ) ;
a . setWord ( base : : RandomValue < uint32 > ( ) ) ;
b = a ;
int32 lim = 1 < < ( i + 23 ) ;
for ( int j = 1 ; j < lim ; j + + ) {
iter + + ;
a . setModMul ( a , a , pq , context ) ;
a . setAdd ( a , BigNum ( uint32 ( t ) ) ) ;
if ( BigNum : : Compare ( a , pq ) > = 0 ) {
a = BigNum : : Sub ( a , pq ) ;
}
if ( BigNum : : Compare ( a , b ) > 0 ) {
q . setSub ( a , b ) ;
} else {
q . setSub ( b , a ) ;
}
p . setGcd ( q , pq , context ) ;
if ( BigNum : : Compare ( p , one ) ! = 0 ) {
found = true ;
break ;
}
if ( ( j & ( j - 1 ) ) = = 0 ) {
b = a ;
}
}
}
if ( ! found ) {
return ParsedPQ ( ) ;
}
BigNum : : Div ( & q , nullptr , pq , p , context ) ;
if ( BigNum : : Compare ( p , q ) > 0 ) {
std : : swap ( p , q ) ;
}
const auto pb = p . getBytes ( ) ;
const auto qb = q . getBytes ( ) ;
return {
QByteArray ( reinterpret_cast < const char * > ( pb . data ( ) ) , pb . size ( ) ) ,
QByteArray ( reinterpret_cast < const char * > ( qb . data ( ) ) , qb . size ( ) )
} ;
}
[[nodiscard]] ParsedPQ FactorizePQ ( const QByteArray & pqStr ) {
const auto size = pqStr . size ( ) ;
if ( size > 8 | | ( size = = 8 & & ( uchar ( pqStr [ 0 ] ) & 128 ) ! = 0 ) ) {
return FactorizeBigPQ ( pqStr ) ;
}
auto ptr = reinterpret_cast < const uchar * > ( pqStr . data ( ) ) ;
uint64 pq = 0 ;
for ( auto i = 0 ; i ! = size ; + + i ) {
pq = ( pq < < 8 ) | ptr [ i ] ;
}
auto p = FactorizeSmallPQ ( pq ) ;
if ( p = = 0 | | ( pq % p ) ! = 0 ) {
return ParsedPQ ( ) ;
}
auto q = pq / p ;
2019-11-13 17:12:04 +03:00
auto pStr = QByteArray ( 4 , Qt : : Uninitialized ) ;
uchar * pChars = ( uchar * ) pStr . data ( ) ;
2021-09-30 21:13:34 +04:00
for ( auto i = 0 ; i ! = 4 ; + + i ) {
2019-11-13 17:12:04 +03:00
* ( pChars + 3 - i ) = ( uchar ) ( p & 0xFF ) ;
p > > = 8 ;
}
auto qStr = QByteArray ( 4 , Qt : : Uninitialized ) ;
uchar * qChars = ( uchar * ) qStr . data ( ) ;
2021-09-30 21:13:34 +04:00
for ( auto i = 0 ; i ! = 4 ; + + i ) {
2019-11-13 17:12:04 +03:00
* ( qChars + 3 - i ) = ( uchar ) ( q & 0xFF ) ;
q > > = 8 ;
}
return { pStr , qStr } ;
}
2021-07-05 15:38:30 +03:00
[[nodiscard]] bool IsGoodEncryptedInner (
bytes : : const_span keyAesEncrypted ,
const RSAPublicKey & key ) {
Expects ( keyAesEncrypted . size ( ) = = 256 ) ;
const auto modulus = key . getN ( ) ;
const auto e = key . getE ( ) ;
const auto shift = ( 256 - int ( modulus . size ( ) ) ) ;
Assert ( shift > = 0 ) ;
for ( auto i = 0 ; i ! = 256 ; + + i ) {
const auto a = keyAesEncrypted [ i ] ;
const auto b = ( i < shift )
? bytes : : type ( 0 )
: modulus [ i - shift ] ;
if ( a > b ) {
return false ;
} else if ( a < b ) {
return true ;
}
}
return false ;
}
2019-11-14 10:13:17 +03:00
template < typename PQInnerData >
2019-11-13 17:12:04 +03:00
[[nodiscard]] bytes : : vector EncryptPQInnerRSA (
2019-11-14 10:13:17 +03:00
const PQInnerData & data ,
2019-11-13 17:12:04 +03:00
const RSAPublicKey & key ) {
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: encrypting pq inner... " ) ) ;
2021-07-05 15:38:30 +03:00
constexpr auto kPrime = sizeof ( mtpPrime ) ;
constexpr auto kDataWithPaddingPrimes = 192 / kPrime ;
constexpr auto kMaxSizeInPrimes = 144 / kPrime ;
constexpr auto kDataHashPrimes = ( SHA256_DIGEST_LENGTH / kPrime ) ;
constexpr auto kKeySize = 32 ;
constexpr auto kIvSize = 32 ;
2019-11-13 17:12:04 +03:00
2019-11-14 16:34:58 +03:00
using BoxedPQInnerData = std : : conditional_t <
tl : : is_boxed_v < PQInnerData > ,
PQInnerData ,
tl : : boxed < PQInnerData > > ;
const auto boxed = BoxedPQInnerData ( data ) ;
const auto p_q_inner_size = tl : : count_length ( boxed ) ;
2021-07-05 15:38:30 +03:00
const auto sizeInPrimes = ( p_q_inner_size / kPrime ) ;
if ( sizeInPrimes > kMaxSizeInPrimes ) {
return { } ;
2019-11-13 17:12:04 +03:00
}
2021-07-05 15:38:30 +03:00
auto dataWithPadding = mtpBuffer ( ) ;
dataWithPadding . reserve ( kDataWithPaddingPrimes ) ;
boxed . write ( dataWithPadding ) ;
// data_with_padding := data + random_padding_bytes;
dataWithPadding . resize ( kDataWithPaddingPrimes ) ;
const auto dataWithPaddingBytes = bytes : : make_span ( dataWithPadding ) ;
bytes : : set_random ( dataWithPaddingBytes . subspan ( sizeInPrimes * kPrime ) ) ;
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: starting key generation for pq inner... " ) ) ;
2021-07-05 15:38:30 +03:00
while ( true ) {
auto dataWithHash = mtpBuffer ( ) ;
dataWithHash . reserve ( kDataWithPaddingPrimes + kDataHashPrimes ) ;
dataWithHash . append ( dataWithPadding ) ;
// data_pad_reversed := BYTE_REVERSE(data_with_padding);
ranges : : reverse ( bytes : : make_span ( dataWithHash ) ) ;
// data_with_hash := data_pad_reversed
// + SHA256(temp_key + data_with_padding);
2021-09-15 13:21:45 +03:00
const auto tempKey = base : : RandomValue < bytes : : array < kKeySize > > ( ) ;
2021-07-05 15:38:30 +03:00
dataWithHash . resize ( kDataWithPaddingPrimes + kDataHashPrimes ) ;
const auto dataWithHashBytes = bytes : : make_span ( dataWithHash ) ;
bytes : : copy (
dataWithHashBytes . subspan ( kDataWithPaddingPrimes * kPrime ) ,
openssl : : Sha256 ( tempKey , bytes : : make_span ( dataWithPadding ) ) ) ;
auto aesEncrypted = mtpBuffer ( ) ;
auto keyAesEncrypted = mtpBuffer ( ) ;
aesEncrypted . resize ( dataWithHash . size ( ) ) ;
const auto aesEncryptedBytes = bytes : : make_span ( aesEncrypted ) ;
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: encrypting ige for pq inner... " ) ) ;
2021-07-05 15:38:30 +03:00
// aes_encrypted := AES256_IGE(data_with_hash, temp_key, 0);
const auto tempIv = bytes : : array < kIvSize > { { bytes : : type ( 0 ) } } ;
aesIgeEncryptRaw (
dataWithHashBytes . data ( ) ,
aesEncryptedBytes . data ( ) ,
dataWithHashBytes . size ( ) ,
tempKey . data ( ) ,
tempIv . data ( ) ) ;
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: counting hash for pq inner... " ) ) ;
2021-07-05 15:38:30 +03:00
// temp_key_xor := temp_key XOR SHA256(aes_encrypted);
const auto fullSize = ( kKeySize / kPrime ) + dataWithHash . size ( ) ;
keyAesEncrypted . resize ( fullSize ) ;
const auto keyAesEncryptedBytes = bytes : : make_span ( keyAesEncrypted ) ;
const auto aesHash = openssl : : Sha256 ( aesEncryptedBytes ) ;
for ( auto i = 0 ; i ! = kKeySize ; + + i ) {
keyAesEncryptedBytes [ i ] = tempKey [ i ] ^ aesHash [ i ] ;
}
2019-11-13 17:12:04 +03:00
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: checking chosen key for pq inner... " ) ) ;
2021-07-05 15:38:30 +03:00
// key_aes_encrypted := temp_key_xor + aes_encrypted;
bytes : : copy (
keyAesEncryptedBytes . subspan ( kKeySize ) ,
aesEncryptedBytes ) ;
if ( IsGoodEncryptedInner ( keyAesEncryptedBytes , key ) ) {
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: chosen key for pq inner is good. " ) ) ;
2021-07-05 15:38:30 +03:00
return key . encrypt ( keyAesEncryptedBytes ) ;
}
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: chosen key for pq inner is bad... " ) ) ;
2021-07-05 15:38:30 +03:00
}
2019-11-13 17:12:04 +03:00
}
[[nodiscard]] std : : string EncryptClientDHInner (
const MTPClient_DH_Inner_Data & data ,
const void * aesKey ,
const void * aesIV ) {
constexpr auto kSkipPrimes = openssl : : kSha1Size / sizeof ( mtpPrime ) ;
auto client_dh_inner_size = tl : : count_length ( data ) ;
auto encSize = ( client_dh_inner_size > > 2 ) + kSkipPrimes ;
auto encFullSize = encSize ;
if ( encSize & 0x03 ) {
encFullSize + = 4 - ( encSize & 0x03 ) ;
}
auto encBuffer = mtpBuffer ( ) ;
encBuffer . reserve ( encFullSize ) ;
encBuffer . resize ( kSkipPrimes ) ;
data . write ( encBuffer ) ;
encBuffer . resize ( encFullSize ) ;
const auto bytes = bytes : : make_span ( encBuffer ) ;
const auto hash = openssl : : Sha1 ( bytes . subspan (
kSkipPrimes * sizeof ( mtpPrime ) ,
client_dh_inner_size ) ) ;
bytes : : copy ( bytes , hash ) ;
bytes : : set_random ( bytes . subspan ( encSize * sizeof ( mtpPrime ) ) ) ;
auto sdhEncString = std : : string ( encFullSize * 4 , ' ' ) ;
aesIgeEncryptRaw ( & encBuffer [ 0 ] , & sdhEncString [ 0 ] , encFullSize * sizeof ( mtpPrime ) , aesKey , aesIV ) ;
return sdhEncString ;
}
// 128 lower-order bits of SHA1.
MTPint128 NonceDigest ( bytes : : const_span data ) {
const auto hash = openssl : : Sha1 ( data ) ;
return * ( MTPint128 * ) ( hash . data ( ) + 4 ) ;
}
} // namespace
2019-11-19 13:10:51 +03:00
DcKeyCreator : : Attempt : : ~ Attempt ( ) {
const auto clearBytes = [ ] ( bytes : : span bytes ) {
OPENSSL_cleanse ( bytes . data ( ) , bytes . size ( ) ) ;
} ;
OPENSSL_cleanse ( & data , sizeof ( data ) ) ;
clearBytes ( dhPrime ) ;
clearBytes ( g_a ) ;
clearBytes ( authKey ) ;
}
2019-11-13 17:12:04 +03:00
DcKeyCreator : : DcKeyCreator (
DcId dcId ,
int16 protocolDcId ,
not_null < AbstractConnection * > connection ,
not_null < DcOptions * > dcOptions ,
2019-11-14 10:13:17 +03:00
Delegate delegate ,
2019-11-20 12:16:53 +03:00
DcKeyRequest request )
2019-11-13 17:12:04 +03:00
: _connection ( connection )
, _dcOptions ( dcOptions )
, _dcId ( dcId )
, _protocolDcId ( protocolDcId )
2019-11-19 13:10:51 +03:00
, _request ( request )
2019-11-13 17:12:04 +03:00
, _delegate ( std : : move ( delegate ) ) {
2019-11-19 13:10:51 +03:00
Expects ( _request . temporaryExpiresIn > 0 ) ;
2019-11-13 17:12:04 +03:00
Expects ( _delegate . done ! = nullptr ) ;
2019-11-19 13:10:51 +03:00
QObject : : connect ( _connection , & AbstractConnection : : receivedData , [ = ] {
answered ( ) ;
} ) ;
if ( _request . persistentNeeded ) {
pqSend ( & _persistent , 0 ) ;
2019-11-19 19:22:02 +03:00
} else {
pqSend ( & _temporary , _request . temporaryExpiresIn ) ;
2019-11-19 13:10:51 +03:00
}
2019-11-13 17:12:04 +03:00
}
DcKeyCreator : : ~ DcKeyCreator ( ) {
2019-11-15 16:04:32 +03:00
if ( _delegate . done ) {
stopReceiving ( ) ;
}
2019-11-13 17:12:04 +03:00
}
2019-11-19 13:10:51 +03:00
template < typename RequestType >
void DcKeyCreator : : sendNotSecureRequest ( const RequestType & request ) {
auto packet = _connection - > prepareNotSecurePacket (
request ,
base : : unixtime : : mtproto_msg_id ( ) ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
DEBUG_LOG ( ( " AuthKey Info: sending request, size: %1, time: %3 "
) . arg ( packet . size ( ) - 8
) . arg ( packet [ 5 ] ) ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
const auto bytesSize = packet . size ( ) * sizeof ( mtpPrime ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
_connection - > sendData ( std : : move ( packet ) ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
if ( _delegate . sentSome ) {
_delegate . sentSome ( bytesSize ) ;
2019-11-13 17:12:04 +03:00
}
2019-11-19 13:10:51 +03:00
}
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
template < typename RequestType , typename Response >
std : : optional < Response > DcKeyCreator : : readNotSecureResponse (
gsl : : span < const mtpPrime > answer ) {
auto from = answer . data ( ) ;
auto result = Response ( ) ;
if ( result . read ( from , from + answer . size ( ) ) ) {
return result ;
2019-11-13 17:12:04 +03:00
}
2019-11-19 13:10:51 +03:00
return std : : nullopt ;
}
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : answered ( ) {
if ( _delegate . receivedSome ) {
_delegate . receivedSome ( ) ;
}
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
if ( _connection - > received ( ) . empty ( ) ) {
LOG ( ( " AuthKey Error: "
" trying to read response from empty received list " ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
const auto buffer = std : : move ( _connection - > received ( ) . front ( ) ) ;
_connection - > received ( ) . pop_front ( ) ;
const auto answer = _connection - > parseNotSecureResponse ( buffer ) ;
if ( answer . empty ( ) ) {
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
handleAnswer ( answer ) ;
}
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
DcKeyCreator : : Attempt * DcKeyCreator : : attemptByNonce ( const MTPint128 & nonce ) {
if ( _temporary . data . nonce = = nonce ) {
DEBUG_LOG ( ( " AuthKey Info: receiving answer for temporary... " ) ) ;
return & _temporary ;
} else if ( _persistent . data . nonce = = nonce ) {
DEBUG_LOG ( ( " AuthKey Info: receiving answer for persistent... " ) ) ;
return & _persistent ;
}
LOG ( ( " AuthKey Error: attempt by nonce not found. " ) ) ;
return nullptr ;
}
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : handleAnswer ( gsl : : span < const mtpPrime > answer ) {
if ( const auto resPQ = readNotSecureResponse < MTPReq_pq > ( answer ) ) {
const auto nonce = resPQ - > match ( [ ] ( const auto & data ) {
return data . vnonce ( ) ;
} ) ;
if ( const auto attempt = attemptByNonce ( nonce ) ) {
DEBUG_LOG ( ( " AuthKey Info: receiving Req_pq answer... " ) ) ;
return pqAnswered ( attempt , * resPQ ) ;
}
} else if ( const auto resDH = readNotSecureResponse < MTPReq_DH_params > ( answer ) ) {
const auto nonce = resDH - > match ( [ ] ( const auto & data ) {
return data . vnonce ( ) ;
} ) ;
if ( const auto attempt = attemptByNonce ( nonce ) ) {
DEBUG_LOG ( ( " AuthKey Info: receiving Req_DH_params answer... " ) ) ;
return dhParamsAnswered ( attempt , * resDH ) ;
}
} else if ( const auto result = readNotSecureResponse < MTPSet_client_DH_params > ( answer ) ) {
const auto nonce = result - > match ( [ ] ( const auto & data ) {
return data . vnonce ( ) ;
} ) ;
if ( const auto attempt = attemptByNonce ( nonce ) ) {
DEBUG_LOG ( ( " AuthKey Info: receiving Req_client_DH_params answer... " ) ) ;
return dhClientParamsAnswered ( attempt , * result ) ;
}
}
LOG ( ( " AuthKey Error: Unknown answer received. " ) ) ;
failed ( ) ;
2019-11-13 17:12:04 +03:00
}
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : pqSend ( not_null < Attempt * > attempt , TimeId expiresIn ) {
DEBUG_LOG ( ( " AuthKey Info: sending Req_pq for %1... "
) . arg ( expiresIn ? " temporary " : " persistent " ) ) ;
attempt - > stage = Stage : : WaitingPQ ;
attempt - > expiresIn = expiresIn ;
2021-09-15 13:21:45 +03:00
attempt - > data . nonce = base : : RandomValue < MTPint128 > ( ) ;
2019-11-19 13:10:51 +03:00
sendNotSecureRequest ( MTPReq_pq_multi ( attempt - > data . nonce ) ) ;
}
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : pqAnswered (
not_null < Attempt * > attempt ,
const MTPresPQ & data ) {
data . match ( [ & ] ( const MTPDresPQ & data ) {
Expects ( data . vnonce ( ) = = attempt - > data . nonce ) ;
if ( attempt - > stage ! = Stage : : WaitingPQ ) {
LOG ( ( " AuthKey Error: Unexpected stage %1 " ) . arg ( int ( attempt - > stage ) ) ) ;
return failed ( ) ;
}
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: getting dc RSA key... " ) ) ;
2019-11-19 13:10:51 +03:00
const auto rsaKey = _dcOptions - > getDcRSAKey (
_dcId ,
data . vserver_public_key_fingerprints ( ) . v ) ;
if ( ! rsaKey . valid ( ) ) {
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Error: unknown public key. " ) ) ;
2019-11-20 12:16:53 +03:00
return failed ( DcKeyError : : UnknownPublicKey ) ;
2019-11-19 13:10:51 +03:00
}
attempt - > data . server_nonce = data . vserver_nonce ( ) ;
2021-09-15 13:21:45 +03:00
attempt - > data . new_nonce = base : : RandomValue < MTPint256 > ( ) ;
2019-11-19 13:10:51 +03:00
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: parsing pq... " ) ) ;
2019-11-19 13:10:51 +03:00
const auto & pq = data . vpq ( ) . v ;
2021-09-30 21:13:34 +04:00
const auto parsed = FactorizePQ ( data . vpq ( ) . v ) ;
2019-11-19 13:10:51 +03:00
if ( parsed . p . isEmpty ( ) | | parsed . q . isEmpty ( ) ) {
LOG ( ( " AuthKey Error: could not factor pq! " ) ) ;
DEBUG_LOG ( ( " AuthKey Error: problematic pq: %1 " ) . arg ( Logs : : mb ( pq . constData ( ) , pq . length ( ) ) . str ( ) ) ) ;
return failed ( ) ;
}
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Info: parse pq done. " ) ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
const auto dhEncString = [ & ] {
return ( attempt - > expiresIn = = 0 )
? EncryptPQInnerRSA (
MTP_p_q_inner_data_dc (
data . vpq ( ) ,
MTP_bytes ( parsed . p ) ,
MTP_bytes ( parsed . q ) ,
attempt - > data . nonce ,
attempt - > data . server_nonce ,
attempt - > data . new_nonce ,
MTP_int ( _protocolDcId ) ) ,
rsaKey )
: EncryptPQInnerRSA (
MTP_p_q_inner_data_temp_dc (
data . vpq ( ) ,
MTP_bytes ( parsed . p ) ,
MTP_bytes ( parsed . q ) ,
attempt - > data . nonce ,
attempt - > data . server_nonce ,
attempt - > data . new_nonce ,
MTP_int ( _protocolDcId ) ,
MTP_int ( attempt - > expiresIn ) ) ,
rsaKey ) ;
} ( ) ;
if ( dhEncString . empty ( ) ) {
2021-09-15 13:21:45 +03:00
DEBUG_LOG ( ( " AuthKey Error: could not encrypt pq inner. " ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
attempt - > stage = Stage : : WaitingDH ;
DEBUG_LOG ( ( " AuthKey Info: sending Req_DH_params... " ) ) ;
sendNotSecureRequest ( MTPReq_DH_params (
attempt - > data . nonce ,
attempt - > data . server_nonce ,
MTP_bytes ( parsed . p ) ,
MTP_bytes ( parsed . q ) ,
MTP_long ( rsaKey . fingerprint ( ) ) ,
MTP_bytes ( dhEncString ) ) ) ;
} ) ;
}
void DcKeyCreator : : dhParamsAnswered (
not_null < Attempt * > attempt ,
const MTPserver_DH_Params & data ) {
if ( attempt - > stage ! = Stage : : WaitingDH ) {
LOG ( ( " AuthKey Error: Unexpected stage %1 " ) . arg ( int ( attempt - > stage ) ) ) ;
return failed ( ) ;
}
data . match ( [ & ] ( const MTPDserver_DH_params_ok & data ) {
Expects ( data . vnonce ( ) = = attempt - > data . nonce ) ;
if ( data . vserver_nonce ( ) ! = attempt - > data . server_nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received server_nonce <> sent server_nonce (in server_DH_params_ok)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
auto & encDHStr = data . vencrypted_answer ( ) . v ;
2019-11-13 17:12:04 +03:00
uint32 encDHLen = encDHStr . length ( ) , encDHBufLen = encDHLen > > 2 ;
if ( ( encDHLen & 0x03 ) | | encDHBufLen < 6 ) {
LOG ( ( " AuthKey Error: bad encrypted data length %1 (in server_DH_params_ok)! " ) . arg ( encDHLen ) ) ;
DEBUG_LOG ( ( " AuthKey Error: received encrypted data %1 " ) . arg ( Logs : : mb ( encDHStr . constData ( ) , encDHLen ) . str ( ) ) ) ;
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
const auto nlen = sizeof ( attempt - > data . new_nonce ) ;
const auto slen = sizeof ( attempt - > data . server_nonce ) ;
2019-11-13 17:12:04 +03:00
auto tmp_aes_buffer = bytes : : array < 1024 > ( ) ;
const auto tmp_aes = bytes : : make_span ( tmp_aes_buffer ) ;
2019-11-19 13:10:51 +03:00
bytes : : copy ( tmp_aes , bytes : : object_as_span ( & attempt - > data . new_nonce ) ) ;
bytes : : copy ( tmp_aes . subspan ( nlen ) , bytes : : object_as_span ( & attempt - > data . server_nonce ) ) ;
bytes : : copy ( tmp_aes . subspan ( nlen + slen ) , bytes : : object_as_span ( & attempt - > data . new_nonce ) ) ;
bytes : : copy ( tmp_aes . subspan ( nlen + slen + nlen ) , bytes : : object_as_span ( & attempt - > data . new_nonce ) ) ;
2019-11-13 17:12:04 +03:00
const auto sha1ns = openssl : : Sha1 ( tmp_aes . subspan ( 0 , nlen + slen ) ) ;
const auto sha1sn = openssl : : Sha1 ( tmp_aes . subspan ( nlen , nlen + slen ) ) ;
const auto sha1nn = openssl : : Sha1 ( tmp_aes . subspan ( nlen + slen , nlen + nlen ) ) ;
mtpBuffer decBuffer ;
decBuffer . resize ( encDHBufLen ) ;
2019-11-19 13:10:51 +03:00
const auto aesKey = bytes : : make_span ( attempt - > data . aesKey ) ;
const auto aesIV = bytes : : make_span ( attempt - > data . aesIV ) ;
2019-11-13 17:12:04 +03:00
bytes : : copy ( aesKey , bytes : : make_span ( sha1ns ) . subspan ( 0 , 20 ) ) ;
bytes : : copy ( aesKey . subspan ( 20 ) , bytes : : make_span ( sha1sn ) . subspan ( 0 , 12 ) ) ;
bytes : : copy ( aesIV , bytes : : make_span ( sha1sn ) . subspan ( 12 , 8 ) ) ;
bytes : : copy ( aesIV . subspan ( 8 ) , bytes : : make_span ( sha1nn ) . subspan ( 0 , 20 ) ) ;
2019-11-19 13:10:51 +03:00
bytes : : copy ( aesIV . subspan ( 28 ) , bytes : : object_as_span ( & attempt - > data . new_nonce ) . subspan ( 0 , 4 ) ) ;
2019-11-13 17:12:04 +03:00
aesIgeDecryptRaw ( encDHStr . constData ( ) , & decBuffer [ 0 ] , encDHLen , aesKey . data ( ) , aesIV . data ( ) ) ;
const mtpPrime * from ( & decBuffer [ 5 ] ) , * to ( from ) , * end ( from + ( encDHBufLen - 5 ) ) ;
MTPServer_DH_inner_data dh_inner ;
if ( ! dh_inner . read ( to , end ) ) {
LOG ( ( " AuthKey Error: could not decrypt server_DH_inner_data! " ) ) ;
return failed ( ) ;
}
const auto & dh_inner_data ( dh_inner . c_server_DH_inner_data ( ) ) ;
2019-11-19 13:10:51 +03:00
if ( dh_inner_data . vnonce ( ) ! = attempt - > data . nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received nonce <> sent nonce (in server_DH_inner_data)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
if ( dh_inner_data . vserver_nonce ( ) ! = attempt - > data . server_nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received server_nonce <> sent server_nonce (in server_DH_inner_data)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
const auto sha1Buffer = openssl : : Sha1 (
bytes : : make_span ( decBuffer ) . subspan (
5 * sizeof ( mtpPrime ) ,
( to - from ) * sizeof ( mtpPrime ) ) ) ;
const auto sha1Dec = bytes : : make_span ( decBuffer ) . subspan (
0 ,
openssl : : kSha1Size ) ;
if ( bytes : : compare ( sha1Dec , sha1Buffer ) ) {
LOG ( ( " AuthKey Error: sha1 hash of encrypted part did not match! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
base : : unixtime : : update ( dh_inner_data . vserver_time ( ) . v ) ;
// check that dhPrime and (dhPrime - 1) / 2 are really prime
if ( ! IsPrimeAndGood ( bytes : : make_span ( dh_inner_data . vdh_prime ( ) . v ) , dh_inner_data . vg ( ) . v ) ) {
LOG ( ( " AuthKey Error: bad dh_prime primality! " ) ) ;
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
attempt - > dhPrime = bytes : : make_vector (
2019-11-13 17:12:04 +03:00
dh_inner_data . vdh_prime ( ) . v ) ;
2019-11-19 13:10:51 +03:00
attempt - > data . g = dh_inner_data . vg ( ) . v ;
attempt - > g_a = bytes : : make_vector ( dh_inner_data . vg_a ( ) . v ) ;
attempt - > data . retry_id = MTP_long ( 0 ) ;
attempt - > retries = 0 ;
dhClientParamsSend ( attempt ) ;
} , [ & ] ( const MTPDserver_DH_params_fail & data ) {
Expects ( data . vnonce ( ) = = attempt - > data . nonce ) ;
if ( data . vserver_nonce ( ) ! = attempt - > data . server_nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received server_nonce <> sent server_nonce (in server_DH_params_fail)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
if ( data . vnew_nonce_hash ( ) ! = NonceDigest ( bytes : : object_as_span ( & attempt - > data . new_nonce ) ) ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received new_nonce_hash did not match! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
LOG ( ( " AuthKey Error: server_DH_params_fail received! " ) ) ;
2019-11-19 13:10:51 +03:00
failed ( ) ;
} ) ;
2019-11-13 17:12:04 +03:00
}
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : dhClientParamsSend ( not_null < Attempt * > attempt ) {
if ( + + attempt - > retries > 5 ) {
LOG ( ( " AuthKey Error: could not create auth_key for %1 retries " ) . arg ( attempt - > retries - 1 ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
// gen rand 'b'
auto randomSeed = bytes : : vector ( ModExpFirst : : kRandomPowerSize ) ;
bytes : : set_random ( randomSeed ) ;
2019-11-19 13:10:51 +03:00
auto g_b_data = CreateModExp ( attempt - > data . g , attempt - > dhPrime , randomSeed ) ;
2019-11-13 17:12:04 +03:00
if ( g_b_data . modexp . empty ( ) ) {
LOG ( ( " AuthKey Error: could not generate good g_b. " ) ) ;
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
auto computedAuthKey = CreateAuthKey ( attempt - > g_a , g_b_data . randomPower , attempt - > dhPrime ) ;
2019-11-13 17:12:04 +03:00
if ( computedAuthKey . empty ( ) ) {
LOG ( ( " AuthKey Error: could not generate auth_key. " ) ) ;
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
AuthKey : : FillData ( attempt - > authKey , computedAuthKey ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
auto auth_key_sha = openssl : : Sha1 ( attempt - > authKey ) ;
2021-04-09 19:17:47 +04:00
memcpy ( & attempt - > data . auth_key_aux_hash . v , auth_key_sha . data ( ) , 8 ) ;
memcpy ( & attempt - > data . auth_key_hash . v , auth_key_sha . data ( ) + 12 , 8 ) ;
2019-11-13 17:12:04 +03:00
const auto client_dh_inner = MTP_client_DH_inner_data (
2019-11-19 13:10:51 +03:00
attempt - > data . nonce ,
attempt - > data . server_nonce ,
attempt - > data . retry_id ,
2019-11-13 17:12:04 +03:00
MTP_bytes ( g_b_data . modexp ) ) ;
auto sdhEncString = EncryptClientDHInner (
client_dh_inner ,
2019-11-19 13:10:51 +03:00
attempt - > data . aesKey . data ( ) ,
attempt - > data . aesIV . data ( ) ) ;
2019-11-13 17:12:04 +03:00
2019-11-19 13:10:51 +03:00
attempt - > stage = Stage : : WaitingDone ;
2019-11-13 17:12:04 +03:00
DEBUG_LOG ( ( " AuthKey Info: sending Req_client_DH_params... " ) ) ;
sendNotSecureRequest ( MTPSet_client_DH_params (
2019-11-19 13:10:51 +03:00
attempt - > data . nonce ,
attempt - > data . server_nonce ,
2019-11-13 17:12:04 +03:00
MTP_string ( std : : move ( sdhEncString ) ) ) ) ;
}
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : dhClientParamsAnswered (
not_null < Attempt * > attempt ,
const MTPset_client_DH_params_answer & data ) {
if ( attempt - > stage ! = Stage : : WaitingDone ) {
LOG ( ( " AuthKey Error: Unexpected stage %1 " ) . arg ( int ( attempt - > stage ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
data . match ( [ & ] ( const MTPDdh_gen_ok & data ) {
if ( data . vnonce ( ) ! = attempt - > data . nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received nonce <> sent nonce (in dh_gen_ok)! " ) ) ;
2021-03-13 15:50:34 +04:00
DEBUG_LOG ( ( " AuthKey Error: received nonce: %1, sent nonce: %2 " ) . arg ( Logs : : mb ( & data . vnonce ( ) , 16 ) . str ( ) , Logs : : mb ( & attempt - > data . nonce , 16 ) . str ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
if ( data . vserver_nonce ( ) ! = attempt - > data . server_nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_ok)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
attempt - > data . new_nonce_buf [ 32 ] = bytes : : type ( 1 ) ;
if ( data . vnew_nonce_hash1 ( ) ! = NonceDigest ( attempt - > data . new_nonce_buf ) ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received new_nonce_hash1 did not match! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
uint64 salt1 = attempt - > data . new_nonce . l . l , salt2 = attempt - > data . server_nonce . l ;
attempt - > data . doneSalt = salt1 ^ salt2 ;
attempt - > stage = Stage : : Ready ;
done ( ) ;
} , [ & ] ( const MTPDdh_gen_retry & data ) {
if ( data . vnonce ( ) ! = attempt - > data . nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received nonce <> sent nonce (in dh_gen_retry)! " ) ) ;
2021-03-13 15:50:34 +04:00
DEBUG_LOG ( ( " AuthKey Error: received nonce: %1, sent nonce: %2 " ) . arg ( Logs : : mb ( & data . vnonce ( ) , 16 ) . str ( ) , Logs : : mb ( & attempt - > data . nonce , 16 ) . str ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
if ( data . vserver_nonce ( ) ! = attempt - > data . server_nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_retry)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
attempt - > data . new_nonce_buf [ 32 ] = bytes : : type ( 2 ) ;
if ( data . vnew_nonce_hash2 ( ) ! = NonceDigest ( attempt - > data . new_nonce_buf ) ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received new_nonce_hash2 did not match! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
attempt - > data . retry_id = attempt - > data . auth_key_aux_hash ;
dhClientParamsSend ( attempt ) ;
} , [ & ] ( const MTPDdh_gen_fail & data ) {
if ( data . vnonce ( ) ! = attempt - > data . nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received nonce <> sent nonce (in dh_gen_fail)! " ) ) ;
2021-03-13 15:50:34 +04:00
DEBUG_LOG ( ( " AuthKey Error: received nonce: %1, sent nonce: %2 " ) . arg ( Logs : : mb ( & data . vnonce ( ) , 16 ) . str ( ) , Logs : : mb ( & attempt - > data . nonce , 16 ) . str ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
if ( data . vserver_nonce ( ) ! = attempt - > data . server_nonce ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received server_nonce <> sent server_nonce (in dh_gen_fail)! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
2019-11-19 13:10:51 +03:00
attempt - > data . new_nonce_buf [ 32 ] = bytes : : type ( 3 ) ;
if ( data . vnew_nonce_hash3 ( ) ! = NonceDigest ( attempt - > data . new_nonce_buf ) ) {
2019-11-13 17:12:04 +03:00
LOG ( ( " AuthKey Error: received new_nonce_hash3 did not match! " ) ) ;
2021-03-13 15:50:34 +04:00
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 ( ) ) ) ;
2019-11-13 17:12:04 +03:00
return failed ( ) ;
}
LOG ( ( " AuthKey Error: dh_gen_fail received! " ) ) ;
2019-11-19 13:10:51 +03:00
failed ( ) ;
} ) ;
2019-11-13 17:12:04 +03:00
}
2019-11-20 12:16:53 +03:00
void DcKeyCreator : : failed ( DcKeyError error ) {
2019-11-15 16:04:32 +03:00
stopReceiving ( ) ;
auto onstack = base : : take ( _delegate . done ) ;
2019-11-13 17:12:04 +03:00
onstack ( tl : : unexpected ( error ) ) ;
}
2019-11-19 13:10:51 +03:00
void DcKeyCreator : : done ( ) {
2019-11-19 19:22:02 +03:00
if ( _temporary . stage = = Stage : : None ) {
pqSend ( & _temporary , _request . temporaryExpiresIn ) ;
2019-11-19 13:10:51 +03:00
return ;
}
2019-11-19 19:22:02 +03:00
Assert ( _temporary . stage = = Stage : : Ready ) ;
Assert ( _persistent . stage = = Stage : : Ready | | _persistent . stage = = Stage : : None ) ;
2019-11-19 13:10:51 +03:00
2019-11-20 12:16:53 +03:00
auto result = DcKeyResult ( ) ;
2019-11-19 13:10:51 +03:00
result . temporaryKey = std : : make_shared < AuthKey > (
AuthKey : : Type : : Temporary ,
2019-11-13 17:12:04 +03:00
_dcId ,
2019-11-19 13:10:51 +03:00
_temporary . authKey ) ;
result . temporaryServerSalt = _temporary . data . doneSalt ;
if ( _persistent . stage = = Stage : : Ready ) {
result . persistentKey = std : : make_shared < AuthKey > (
AuthKey : : Type : : Generated ,
_dcId ,
_persistent . authKey ) ;
result . persistentServerSalt = _persistent . data . doneSalt ;
}
2019-11-15 16:04:32 +03:00
stopReceiving ( ) ;
auto onstack = base : : take ( _delegate . done ) ;
2019-11-13 17:12:04 +03:00
onstack ( std : : move ( result ) ) ;
}
2019-11-15 16:04:32 +03:00
void DcKeyCreator : : stopReceiving ( ) {
QObject : : disconnect (
_connection ,
& AbstractConnection : : receivedData ,
nullptr ,
nullptr ) ;
}
2019-11-13 17:12:04 +03:00
} // namespace MTP::details