diff --git a/CMakeLists.txt b/CMakeLists.txt index fbd7f4212..d8407dbda 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,6 +328,7 @@ set(TL_DOTNET_SCHEME_SOURCE set(TDLIB_SOURCE td/mtproto/AuthData.cpp td/mtproto/crypto.cpp + td/mtproto/DhHandshake.cpp td/mtproto/Handshake.cpp td/mtproto/HandshakeActor.cpp td/mtproto/HttpTransport.cpp @@ -441,6 +442,7 @@ set(TDLIB_SOURCE td/mtproto/AuthKey.h td/mtproto/crypto.h td/mtproto/CryptoStorer.h + td/mtproto/DhHandshake.h td/mtproto/Handshake.h td/mtproto/HandshakeActor.h td/mtproto/HandshakeConnection.h diff --git a/benchmark/bench_handshake.cpp b/benchmark/bench_handshake.cpp index f59afe608..05f3185ff 100644 --- a/benchmark/bench_handshake.cpp +++ b/benchmark/bench_handshake.cpp @@ -6,7 +6,7 @@ // #include "td/utils/benchmark.h" // for bench, do_not_optimize_away, etc -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/utils/base64.h" #include "td/utils/logging.h" diff --git a/td/mtproto/DhHandshake.cpp b/td/mtproto/DhHandshake.cpp new file mode 100644 index 000000000..f9f7240b8 --- /dev/null +++ b/td/mtproto/DhHandshake.cpp @@ -0,0 +1,231 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/mtproto/DhHandshake.h" + +#include "td/utils/as.h" +#include "td/utils/crypto.h" +#include "td/utils/logging.h" +#include "td/utils/misc.h" +#include "td/utils/Random.h" +#include "td/utils/Slice.h" +#include "td/utils/Status.h" + +#include + +namespace td { + +Status DhHandshake::check_config(Slice prime_str, const BigNum &prime, int32 g_int, BigNumContext &ctx, + DhCallback *callback) { + // check that 2^2047 <= p < 2^2048 + if (prime.get_num_bits() != 2048) { + return Status::Error("p is not 2048-bit number"); + } + + // g generates a cyclic subgroup of prime order (p - 1) / 2, i.e. is a quadratic residue mod p. + // Since g is always equal to 2, 3, 4, 5, 6 or 7, this is easily done using quadratic reciprocity law, + // yielding a simple condition on + // * p mod 4g - namely, p mod 8 = 7 for g = 2; p mod 3 = 2 for g = 3; + // * no extra condition for g = 4; + // * p mod 5 = 1 or 4 for g = 5; + // * p mod 24 = 19 or 23 for g = 6; + // * p mod 7 = 3, 5 or 6 for g = 7. + + bool mod_ok; + uint32 mod_r; + switch (g_int) { + case 2: + mod_ok = prime % 8 == 7u; + break; + case 3: + mod_ok = prime % 3 == 2u; + break; + case 4: + mod_ok = true; + break; + case 5: + mod_ok = (mod_r = prime % 5) == 1u || mod_r == 4u; + break; + case 6: + mod_ok = (mod_r = prime % 24) == 19u || mod_r == 23u; + break; + case 7: + mod_ok = (mod_r = prime % 7) == 3u || mod_r == 5u || mod_r == 6u; + break; + default: + mod_ok = false; + } + if (!mod_ok) { + return Status::Error("Bad prime mod 4g"); + } + + // check whether p is a safe prime (meaning that both p and (p - 1) / 2 are prime) + int is_good_prime = -1; + if (callback) { + is_good_prime = callback->is_good_prime(prime_str); + } + if (is_good_prime != -1) { + return is_good_prime ? Status::OK() : Status::Error("p or (p - 1) / 2 is not a prime number"); + } + if (!prime.is_prime(ctx)) { + if (callback) { + callback->add_bad_prime(prime_str); + } + return Status::Error("p is not a prime number"); + } + + BigNum half_prime = prime; + half_prime -= 1; + half_prime /= 2; + if (!half_prime.is_prime(ctx)) { + if (callback) { + callback->add_bad_prime(prime_str); + } + return Status::Error("(p - 1) / 2 is not a prime number"); + } + if (callback) { + callback->add_good_prime(prime_str); + } + return Status::OK(); +} + +Status DhHandshake::dh_check(const BigNum &prime, const BigNum &g_a, const BigNum &g_b) { + // IMPORTANT: Apart from the conditions on the Diffie-Hellman prime dh_prime and generator g, both sides are + // to check that g, g_a and g_b are greater than 1 and less than dh_prime - 1. + // We recommend checking that g_a and g_b are between 2^{2048-64} and dh_prime - 2^{2048-64} as well. + + CHECK(prime.get_num_bits() == 2048); + BigNum left; + left.set_value(0); + left.set_bit(2048 - 64); + + BigNum right; + BigNum::sub(right, prime, left); + + if (BigNum::compare(left, g_a) > 0 || BigNum::compare(g_a, right) > 0 || BigNum::compare(left, g_b) > 0 || + BigNum::compare(g_b, right) > 0) { + std::string x(2048, '0'); + std::string y(2048, '0'); + for (int i = 0; i < 2048; i++) { + if (g_a.is_bit_set(i)) { + x[i] = '1'; + } + if (g_b.is_bit_set(i)) { + y[i] = '1'; + } + } + LOG(ERROR) << x; + LOG(ERROR) << y; + return Status::Error("g^a or g^b is not between 2^{2048-64} and dh_prime - 2^{2048-64}"); + } + + return Status::OK(); +} + +void DhHandshake::set_config(int32 g_int, Slice prime_str) { + has_config_ = true; + prime_ = BigNum::from_binary(prime_str); + prime_str_ = prime_str.str(); + + b_ = BigNum(); + g_b_ = BigNum(); + + BigNum::random(b_, 2048, -1, 0); + + // g^b + g_int_ = g_int; + g_.set_value(g_int_); + + BigNum::mod_exp(g_b_, g_, b_, prime_, ctx_); +} + +Status DhHandshake::check_config(int32 g_int, Slice prime_str, DhCallback *callback) { + BigNumContext ctx; + auto prime = BigNum::from_binary(prime_str); + return check_config(prime_str, prime, g_int, ctx, callback); +} + +void DhHandshake::set_g_a_hash(Slice g_a_hash) { + has_g_a_hash_ = true; + ok_g_a_hash_ = false; + CHECK(!has_g_a_); + g_a_hash_ = g_a_hash.str(); +} + +void DhHandshake::set_g_a(Slice g_a_str) { + has_g_a_ = true; + if (has_g_a_hash_) { + string g_a_hash(32, ' '); + sha256(g_a_str, g_a_hash); + ok_g_a_hash_ = g_a_hash == g_a_hash_; + } + g_a_ = BigNum::from_binary(g_a_str); +} + +string DhHandshake::get_g_a() const { + CHECK(has_g_a_); + return g_a_.to_binary(); +} + +string DhHandshake::get_g_b() const { + CHECK(has_config_); + return g_b_.to_binary(); +} +string DhHandshake::get_g_b_hash() const { + string g_b_hash(32, ' '); + sha256(get_g_b(), g_b_hash); + return g_b_hash; +} + +Status DhHandshake::run_checks(bool skip_config_check, DhCallback *callback) { + CHECK(has_g_a_ && has_config_); + + if (has_g_a_hash_ && !ok_g_a_hash_) { + return Status::Error("g_a_hash mismatch"); + } + + if (!skip_config_check) { + TRY_STATUS(check_config(prime_str_, prime_, g_int_, ctx_, callback)); + } + + return dh_check(prime_, g_a_, g_b_); +} + +BigNum DhHandshake::get_g() const { + CHECK(has_config_); + return g_; +} + +BigNum DhHandshake::get_p() const { + CHECK(has_config_); + return prime_; +} + +BigNum DhHandshake::get_b() const { + CHECK(has_config_); + return b_; +} + +BigNum DhHandshake::get_g_ab() { + CHECK(has_g_a_ && has_config_); + BigNum g_ab; + BigNum::mod_exp(g_ab, g_a_, b_, prime_, ctx_); + return g_ab; +} + +std::pair DhHandshake::gen_key() { + string key = get_g_ab().to_binary(2048 / 8); + auto key_id = calc_key_id(key); + return std::pair(key_id, std::move(key)); +} + +int64 DhHandshake::calc_key_id(Slice auth_key) { + UInt<160> auth_key_sha1; + sha1(auth_key, auth_key_sha1.raw); + return as(auth_key_sha1.raw + 12); +} + +} // namespace td diff --git a/td/mtproto/DhHandshake.h b/td/mtproto/DhHandshake.h new file mode 100644 index 000000000..e360f5b12 --- /dev/null +++ b/td/mtproto/DhHandshake.h @@ -0,0 +1,135 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/utils/BigNum.h" +#include "td/utils/common.h" +#include "td/utils/Slice.h" +#include "td/utils/Status.h" + +#include + +namespace td { + +/*** DH ***/ +class DhCallback { + public: + DhCallback() = default; + DhCallback(const DhCallback &) = delete; + DhCallback &operator=(const DhCallback &) = delete; + DhCallback(DhCallback &&) = delete; + DhCallback &operator=(DhCallback &&) = delete; + virtual ~DhCallback() = default; + + virtual int is_good_prime(Slice prime_str) const = 0; + virtual void add_good_prime(Slice prime_str) const = 0; + virtual void add_bad_prime(Slice prime_str) const = 0; +}; + +class DhHandshake { + public: + void set_config(int32 g_int, Slice prime_str); + + static Status check_config(int32 g_int, Slice prime_str, DhCallback *callback); + + bool has_config() const { + return has_config_; + } + void set_g_a_hash(Slice g_a_hash); + void set_g_a(Slice g_a_str); + bool has_g_a() const { + return has_g_a_; + } + string get_g_a() const; + string get_g_b() const; + string get_g_b_hash() const; + Status run_checks(bool skip_config_check, DhCallback *callback) TD_WARN_UNUSED_RESULT; + + BigNum get_g() const; + BigNum get_p() const; + BigNum get_b() const; + BigNum get_g_ab(); + + std::pair gen_key(); + + static int64 calc_key_id(Slice auth_key); + + enum Flags { HasConfig = 1, HasGA = 2 }; + + template + void store(StorerT &storer) const { + auto flags = 0; + if (has_config_) { + flags |= HasConfig; + } + if (has_g_a_) { + flags |= HasGA; + } + storer.store_int(flags); + + if (has_config_) { + // prime_, prime_str_, b_, g_, g_int_, g_b_ + storer.store_string(prime_str_); + storer.store_string(b_.to_binary()); + storer.store_int(g_int_); + storer.store_string(g_b_.to_binary()); + } + if (has_g_a_) { + storer.store_string(g_a_.to_binary()); + } + } + template + void parse(ParserT &parser) { + auto flags = parser.fetch_int(); + if (flags & HasConfig) { + has_config_ = true; + } + if (flags & HasGA) { + has_g_a_ = true; + } + if (has_config_) { + // prime_, prime_str_, b_, g_, g_int_, g_b_ + prime_str_ = parser.template fetch_string(); + prime_ = BigNum::from_binary(prime_str_); + + b_ = BigNum::from_binary(parser.template fetch_string()); + + g_int_ = parser.fetch_int(); + g_.set_value(g_int_); + + g_b_ = BigNum::from_binary(parser.template fetch_string()); + } + if (has_g_a_) { + g_a_ = BigNum::from_binary(parser.template fetch_string()); + } + } + + private: + static Status check_config(Slice prime_str, const BigNum &prime, int32 g_int, BigNumContext &ctx, + DhCallback *callback) TD_WARN_UNUSED_RESULT; + + static Status dh_check(const BigNum &prime, const BigNum &g_a, const BigNum &g_b) TD_WARN_UNUSED_RESULT; + + string prime_str_; + BigNum prime_; + BigNum g_; + int32 g_int_; + BigNum b_; + BigNum g_b_; + BigNum g_a_; + + string g_a_hash_; + bool has_g_a_hash_{false}; + bool ok_g_a_hash_{false}; + + bool has_config_ = false; + bool has_g_a_ = false; + + BigNumContext ctx_; +}; + +} // namespace td diff --git a/td/mtproto/Handshake.cpp b/td/mtproto/Handshake.cpp index d693cbe6f..6afa277a5 100644 --- a/td/mtproto/Handshake.cpp +++ b/td/mtproto/Handshake.cpp @@ -6,6 +6,7 @@ // #include "td/mtproto/Handshake.h" +#include "td/mtproto/crypto.h" #include "td/mtproto/utils.h" #include "td/mtproto/mtproto_api.h" diff --git a/td/mtproto/Handshake.h b/td/mtproto/Handshake.h index a71ea3ef9..7c28a514d 100644 --- a/td/mtproto/Handshake.h +++ b/td/mtproto/Handshake.h @@ -8,6 +8,7 @@ #include "td/mtproto/AuthKey.h" #include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/utils/buffer.h" #include "td/utils/Slice.h" diff --git a/td/mtproto/HandshakeConnection.h b/td/mtproto/HandshakeConnection.h index 53aae3ee3..f9e9f44e8 100644 --- a/td/mtproto/HandshakeConnection.h +++ b/td/mtproto/HandshakeConnection.h @@ -12,8 +12,6 @@ #include "td/mtproto/PacketInfo.h" #include "td/mtproto/PacketStorer.h" #include "td/mtproto/RawConnection.h" -#include "td/mtproto/Transport.h" -#include "td/mtproto/utils.h" #include "td/utils/buffer.h" #include "td/utils/common.h" diff --git a/td/mtproto/SessionConnection.cpp b/td/mtproto/SessionConnection.cpp index db0fb6be1..b7e8e8ecc 100644 --- a/td/mtproto/SessionConnection.cpp +++ b/td/mtproto/SessionConnection.cpp @@ -10,6 +10,7 @@ #include "td/mtproto/CryptoStorer.h" #include "td/mtproto/PacketStorer.h" #include "td/mtproto/Transport.h" +#include "td/mtproto/utils.h" #include "td/utils/as.h" #include "td/utils/format.h" diff --git a/td/mtproto/SessionConnection.h b/td/mtproto/SessionConnection.h index 5a3173523..ad7ad2839 100644 --- a/td/mtproto/SessionConnection.h +++ b/td/mtproto/SessionConnection.h @@ -6,9 +6,9 @@ // #pragma once -#include "td/mtproto/RawConnection.h" #include "td/mtproto/PacketInfo.h" #include "td/mtproto/Query.h" +#include "td/mtproto/RawConnection.h" #include "td/utils/buffer.h" #include "td/utils/format.h" diff --git a/td/mtproto/TcpTransport.h b/td/mtproto/TcpTransport.h index 440483275..b1e0b6bfc 100644 --- a/td/mtproto/TcpTransport.h +++ b/td/mtproto/TcpTransport.h @@ -7,6 +7,7 @@ #pragma once #include "td/mtproto/IStreamTransport.h" +#include "td/mtproto/TransportType.h" #include "td/utils/AesCtrByteFlow.h" #include "td/utils/buffer.h" diff --git a/td/mtproto/crypto.cpp b/td/mtproto/crypto.cpp index 167885849..e02f43e58 100644 --- a/td/mtproto/crypto.cpp +++ b/td/mtproto/crypto.cpp @@ -130,216 +130,6 @@ void RSA::decrypt(Slice from, MutableSlice to) const { std::memcpy(to.data(), result.c_str(), 256); } -Status DhHandshake::check_config(Slice prime_str, const BigNum &prime, int32 g_int, BigNumContext &ctx, - DhCallback *callback) { - // check that 2^2047 <= p < 2^2048 - if (prime.get_num_bits() != 2048) { - return Status::Error("p is not 2048-bit number"); - } - - // g generates a cyclic subgroup of prime order (p - 1) / 2, i.e. is a quadratic residue mod p. - // Since g is always equal to 2, 3, 4, 5, 6 or 7, this is easily done using quadratic reciprocity law, - // yielding a simple condition on - // * p mod 4g - namely, p mod 8 = 7 for g = 2; p mod 3 = 2 for g = 3; - // * no extra condition for g = 4; - // * p mod 5 = 1 or 4 for g = 5; - // * p mod 24 = 19 or 23 for g = 6; - // * p mod 7 = 3, 5 or 6 for g = 7. - - bool mod_ok; - uint32 mod_r; - switch (g_int) { - case 2: - mod_ok = prime % 8 == 7u; - break; - case 3: - mod_ok = prime % 3 == 2u; - break; - case 4: - mod_ok = true; - break; - case 5: - mod_ok = (mod_r = prime % 5) == 1u || mod_r == 4u; - break; - case 6: - mod_ok = (mod_r = prime % 24) == 19u || mod_r == 23u; - break; - case 7: - mod_ok = (mod_r = prime % 7) == 3u || mod_r == 5u || mod_r == 6u; - break; - default: - mod_ok = false; - } - if (!mod_ok) { - return Status::Error("Bad prime mod 4g"); - } - - // check whether p is a safe prime (meaning that both p and (p - 1) / 2 are prime) - int is_good_prime = -1; - if (callback) { - is_good_prime = callback->is_good_prime(prime_str); - } - if (is_good_prime != -1) { - return is_good_prime ? Status::OK() : Status::Error("p or (p - 1) / 2 is not a prime number"); - } - if (!prime.is_prime(ctx)) { - if (callback) { - callback->add_bad_prime(prime_str); - } - return Status::Error("p is not a prime number"); - } - - BigNum half_prime = prime; - half_prime -= 1; - half_prime /= 2; - if (!half_prime.is_prime(ctx)) { - if (callback) { - callback->add_bad_prime(prime_str); - } - return Status::Error("(p - 1) / 2 is not a prime number"); - } - if (callback) { - callback->add_good_prime(prime_str); - } - return Status::OK(); -} - -Status DhHandshake::dh_check(const BigNum &prime, const BigNum &g_a, const BigNum &g_b) { - // IMPORTANT: Apart from the conditions on the Diffie-Hellman prime dh_prime and generator g, both sides are - // to check that g, g_a and g_b are greater than 1 and less than dh_prime - 1. - // We recommend checking that g_a and g_b are between 2^{2048-64} and dh_prime - 2^{2048-64} as well. - - CHECK(prime.get_num_bits() == 2048); - BigNum left; - left.set_value(0); - left.set_bit(2048 - 64); - - BigNum right; - BigNum::sub(right, prime, left); - - if (BigNum::compare(left, g_a) > 0 || BigNum::compare(g_a, right) > 0 || BigNum::compare(left, g_b) > 0 || - BigNum::compare(g_b, right) > 0) { - std::string x(2048, '0'); - std::string y(2048, '0'); - for (int i = 0; i < 2048; i++) { - if (g_a.is_bit_set(i)) { - x[i] = '1'; - } - if (g_b.is_bit_set(i)) { - y[i] = '1'; - } - } - LOG(ERROR) << x; - LOG(ERROR) << y; - return Status::Error("g^a or g^b is not between 2^{2048-64} and dh_prime - 2^{2048-64}"); - } - - return Status::OK(); -} - -void DhHandshake::set_config(int32 g_int, Slice prime_str) { - has_config_ = true; - prime_ = BigNum::from_binary(prime_str); - prime_str_ = prime_str.str(); - - b_ = BigNum(); - g_b_ = BigNum(); - - BigNum::random(b_, 2048, -1, 0); - - // g^b - g_int_ = g_int; - g_.set_value(g_int_); - - BigNum::mod_exp(g_b_, g_, b_, prime_, ctx_); -} - -Status DhHandshake::check_config(int32 g_int, Slice prime_str, DhCallback *callback) { - BigNumContext ctx; - auto prime = BigNum::from_binary(prime_str); - return check_config(prime_str, prime, g_int, ctx, callback); -} - -void DhHandshake::set_g_a_hash(Slice g_a_hash) { - has_g_a_hash_ = true; - ok_g_a_hash_ = false; - CHECK(!has_g_a_); - g_a_hash_ = g_a_hash.str(); -} - -void DhHandshake::set_g_a(Slice g_a_str) { - has_g_a_ = true; - if (has_g_a_hash_) { - string g_a_hash(32, ' '); - sha256(g_a_str, g_a_hash); - ok_g_a_hash_ = g_a_hash == g_a_hash_; - } - g_a_ = BigNum::from_binary(g_a_str); -} - -string DhHandshake::get_g_a() const { - CHECK(has_g_a_); - return g_a_.to_binary(); -} - -string DhHandshake::get_g_b() const { - CHECK(has_config_); - return g_b_.to_binary(); -} -string DhHandshake::get_g_b_hash() const { - string g_b_hash(32, ' '); - sha256(get_g_b(), g_b_hash); - return g_b_hash; -} - -Status DhHandshake::run_checks(bool skip_config_check, DhCallback *callback) { - CHECK(has_g_a_ && has_config_); - - if (has_g_a_hash_ && !ok_g_a_hash_) { - return Status::Error("g_a_hash mismatch"); - } - - if (!skip_config_check) { - TRY_STATUS(check_config(prime_str_, prime_, g_int_, ctx_, callback)); - } - - return dh_check(prime_, g_a_, g_b_); -} - -BigNum DhHandshake::get_g() const { - CHECK(has_config_); - return g_; -} - -BigNum DhHandshake::get_p() const { - CHECK(has_config_); - return prime_; -} - -BigNum DhHandshake::get_b() const { - CHECK(has_config_); - return b_; -} - -BigNum DhHandshake::get_g_ab() { - CHECK(has_g_a_ && has_config_); - BigNum g_ab; - BigNum::mod_exp(g_ab, g_a_, b_, prime_, ctx_); - return g_ab; -} - -std::pair DhHandshake::gen_key() { - string key = get_g_ab().to_binary(2048 / 8); - auto key_id = calc_key_id(key); - return std::pair(key_id, std::move(key)); -} - -int64 DhHandshake::calc_key_id(Slice auth_key) { - UInt<160> auth_key_sha1; - sha1(auth_key, auth_key_sha1.raw); - return as(auth_key_sha1.raw + 12); -} - /*** KDF ***/ void KDF(const string &auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt256 *aes_iv) { CHECK(auth_key.size() == 2048 / 8); @@ -434,4 +224,5 @@ void KDF2(Slice auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt2 aes_iv_slice.substr(8).copy_from(sha256_a.substr(8, 16)); aes_iv_slice.substr(24).copy_from(sha256_b.substr(24, 8)); } + } // namespace td diff --git a/td/mtproto/crypto.h b/td/mtproto/crypto.h index fd0960a33..5552ffb21 100644 --- a/td/mtproto/crypto.h +++ b/td/mtproto/crypto.h @@ -42,123 +42,6 @@ class PublicRsaKeyInterface { virtual void drop_keys() = 0; }; -/*** DH ***/ -class DhCallback { - public: - DhCallback() = default; - DhCallback(const DhCallback &) = delete; - DhCallback &operator=(const DhCallback &) = delete; - DhCallback(DhCallback &&) = delete; - DhCallback &operator=(DhCallback &&) = delete; - virtual ~DhCallback() = default; - - virtual int is_good_prime(Slice prime_str) const = 0; - virtual void add_good_prime(Slice prime_str) const = 0; - virtual void add_bad_prime(Slice prime_str) const = 0; -}; - -class DhHandshake { - public: - void set_config(int32 g_int, Slice prime_str); - - static Status check_config(int32 g_int, Slice prime_str, DhCallback *callback); - - bool has_config() const { - return has_config_; - } - void set_g_a_hash(Slice g_a_hash); - void set_g_a(Slice g_a_str); - bool has_g_a() const { - return has_g_a_; - } - string get_g_a() const; - string get_g_b() const; - string get_g_b_hash() const; - Status run_checks(bool skip_config_check, DhCallback *callback) TD_WARN_UNUSED_RESULT; - - BigNum get_g() const; - BigNum get_p() const; - BigNum get_b() const; - BigNum get_g_ab(); - - std::pair gen_key(); - - static int64 calc_key_id(Slice auth_key); - - enum Flags { HasConfig = 1, HasGA = 2 }; - - template - void store(StorerT &storer) const { - auto flags = 0; - if (has_config_) { - flags |= HasConfig; - } - if (has_g_a_) { - flags |= HasGA; - } - storer.store_int(flags); - - if (has_config_) { - // prime_, prime_str_, b_, g_, g_int_, g_b_ - storer.store_string(prime_str_); - storer.store_string(b_.to_binary()); - storer.store_int(g_int_); - storer.store_string(g_b_.to_binary()); - } - if (has_g_a_) { - storer.store_string(g_a_.to_binary()); - } - } - template - void parse(ParserT &parser) { - auto flags = parser.fetch_int(); - if (flags & HasConfig) { - has_config_ = true; - } - if (flags & HasGA) { - has_g_a_ = true; - } - if (has_config_) { - // prime_, prime_str_, b_, g_, g_int_, g_b_ - prime_str_ = parser.template fetch_string(); - prime_ = BigNum::from_binary(prime_str_); - - b_ = BigNum::from_binary(parser.template fetch_string()); - - g_int_ = parser.fetch_int(); - g_.set_value(g_int_); - - g_b_ = BigNum::from_binary(parser.template fetch_string()); - } - if (has_g_a_) { - g_a_ = BigNum::from_binary(parser.template fetch_string()); - } - } - - private: - static Status check_config(Slice prime_str, const BigNum &prime, int32 g_int, BigNumContext &ctx, - DhCallback *callback) TD_WARN_UNUSED_RESULT; - - static Status dh_check(const BigNum &prime, const BigNum &g_a, const BigNum &g_b) TD_WARN_UNUSED_RESULT; - - string prime_str_; - BigNum prime_; - BigNum g_; - int32 g_int_; - BigNum b_; - BigNum g_b_; - BigNum g_a_; - - string g_a_hash_; - bool has_g_a_hash_{false}; - bool ok_g_a_hash_{false}; - - bool has_config_ = false; - bool has_g_a_ = false; - - BigNumContext ctx_; -}; - /*** KDF ***/ void KDF(const string &auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt256 *aes_iv); void tmp_KDF(const UInt128 &server_nonce, const UInt256 &new_nonce, UInt256 *tmp_aes_key, UInt256 *tmp_aes_iv); diff --git a/td/telegram/CallActor.cpp b/td/telegram/CallActor.cpp index 172bd2e45..ce7267e70 100644 --- a/td/telegram/CallActor.cpp +++ b/td/telegram/CallActor.cpp @@ -10,8 +10,6 @@ #include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.hpp" -#include "td/mtproto/crypto.h" - #include "td/telegram/ConfigShared.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/DhCache.h" diff --git a/td/telegram/CallActor.h b/td/telegram/CallActor.h index 452de3294..1467c0ac5 100644 --- a/td/telegram/CallActor.h +++ b/td/telegram/CallActor.h @@ -9,7 +9,7 @@ #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/telegram/CallDiscardReason.h" #include "td/telegram/CallId.h" diff --git a/td/telegram/DeviceTokenManager.cpp b/td/telegram/DeviceTokenManager.cpp index 2f6afd8da..00b0f0424 100644 --- a/td/telegram/DeviceTokenManager.cpp +++ b/td/telegram/DeviceTokenManager.cpp @@ -15,7 +15,7 @@ #include "td/telegram/td_api.hpp" #include "td/telegram/telegram_api.h" -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/utils/base64.h" #include "td/utils/buffer.h" diff --git a/td/telegram/DhCache.h b/td/telegram/DhCache.h index e8042b10b..29cd26db8 100644 --- a/td/telegram/DhCache.h +++ b/td/telegram/DhCache.h @@ -6,7 +6,7 @@ // #pragma once -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/utils/Slice.h" diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index 1c83d4b05..9b65e6bd6 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -13,7 +13,7 @@ #include "td/telegram/SecureStorage.h" #include "td/telegram/TdDb.h" -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/utils/BigNum.h" #include "td/utils/buffer.h" diff --git a/td/telegram/SecretChatActor.h b/td/telegram/SecretChatActor.h index d57c28d2b..682902c3c 100644 --- a/td/telegram/SecretChatActor.h +++ b/td/telegram/SecretChatActor.h @@ -13,7 +13,7 @@ #include "td/actor/PromiseFuture.h" #include "td/mtproto/AuthKey.h" -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/telegram/DhConfig.h" #include "td/telegram/logevent/SecretChatEvent.h" diff --git a/td/telegram/SecretChatsManager.cpp b/td/telegram/SecretChatsManager.cpp index 967ac59a5..704ba5112 100644 --- a/td/telegram/SecretChatsManager.cpp +++ b/td/telegram/SecretChatsManager.cpp @@ -22,7 +22,7 @@ #include "td/telegram/secret_api.h" #include "td/telegram/telegram_api.hpp" -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/actor/PromiseFuture.h" diff --git a/td/telegram/net/Session.cpp b/td/telegram/net/Session.cpp index c77664ebf..bd3d55625 100644 --- a/td/telegram/net/Session.cpp +++ b/td/telegram/net/Session.cpp @@ -18,6 +18,7 @@ #include "td/telegram/UniqueId.h" #include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/mtproto/Handshake.h" #include "td/mtproto/HandshakeActor.h" #include "td/mtproto/RawConnection.h" diff --git a/test/mtproto.cpp b/test/mtproto.cpp index 2b280596b..403e77725 100644 --- a/test/mtproto.cpp +++ b/test/mtproto.cpp @@ -10,11 +10,11 @@ #include "td/actor/PromiseFuture.h" #include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/mtproto/Handshake.h" #include "td/mtproto/HandshakeActor.h" #include "td/mtproto/PingConnection.h" #include "td/mtproto/RawConnection.h" -#include "td/mtproto/Transport.h" #include "td/mtproto/TransportType.h" #include "td/net/GetHostByNameActor.h" diff --git a/test/secret.cpp b/test/secret.cpp index 175d8e78e..bb5584d25 100644 --- a/test/secret.cpp +++ b/test/secret.cpp @@ -20,7 +20,7 @@ #include "td/db/BinlogKeyValue.h" #include "td/db/DbKey.h" -#include "td/mtproto/crypto.h" +#include "td/mtproto/DhHandshake.h" #include "td/mtproto/utils.h" #include "td/tl/tl_object_parse.h"