Mtproto: use non-deterministic padding scheme
GitOrigin-RevId: 3f6ab9ed7b9bbc8ad3ddfabe7d324175cb7e6d49
This commit is contained in:
parent
b938ca635c
commit
13627727ef
@ -100,6 +100,10 @@ size_t Transport::max_append_size() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Transport::use_random_padding() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
} // namespace mtproto
|
||||
} // namespace td
|
||||
|
@ -42,6 +42,7 @@ class Transport : public IStreamTransport {
|
||||
TransportType get_type() const override {
|
||||
return {TransportType::Http, 0, secret_};
|
||||
}
|
||||
bool use_random_padding() const override;
|
||||
|
||||
private:
|
||||
string secret_;
|
||||
|
@ -31,6 +31,7 @@ class IStreamTransport {
|
||||
virtual size_t max_prepend_size() const = 0;
|
||||
virtual size_t max_append_size() const = 0;
|
||||
virtual TransportType get_type() const = 0;
|
||||
virtual bool use_random_padding() const = 0;
|
||||
};
|
||||
|
||||
unique_ptr<IStreamTransport> create_transport(TransportType type);
|
||||
|
@ -27,6 +27,8 @@ struct PacketInfo {
|
||||
bool no_crypto_flag;
|
||||
bool is_creator{false};
|
||||
bool check_mod4{true};
|
||||
bool use_random_padding{false};
|
||||
uint32 size{0};
|
||||
};
|
||||
|
||||
} // namespace mtproto
|
||||
|
@ -27,6 +27,7 @@ void RawConnection::send_crypto(const Storer &storer, int64 session_id, int64 sa
|
||||
info.no_crypto_flag = false;
|
||||
info.salt = salt;
|
||||
info.session_id = session_id;
|
||||
info.use_random_padding = transport_->use_random_padding();
|
||||
|
||||
auto packet = BufferWriter{Transport::write(storer, auth_key, &info), transport_->max_prepend_size(),
|
||||
transport_->max_append_size()};
|
||||
|
@ -61,7 +61,7 @@ void IntermediateTransport::write_prepare_inplace(BufferWriter *message, bool qu
|
||||
|
||||
size_t append_size = 0;
|
||||
if (with_padding()) {
|
||||
append_size = static_cast<uint32>(Random::secure_int32()) % 16;
|
||||
append_size = Random::secure_uint32() % 16;
|
||||
MutableSlice append = message->prepare_append().truncate(append_size);
|
||||
CHECK(append.size() == append_size);
|
||||
Random::secure_bytes(append);
|
||||
@ -170,15 +170,16 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp
|
||||
string rheader = header;
|
||||
std::reverse(rheader.begin(), rheader.end());
|
||||
UInt256 key = as<UInt256>(rheader.data() + 8);
|
||||
if (secret_.size() == 17) {
|
||||
secret_ = secret_.substr(1);
|
||||
Slice secret_view = secret_;
|
||||
if (secret_view.size() == 17) {
|
||||
secret_view.remove_prefix(1);
|
||||
}
|
||||
auto fix_key = [&](UInt256 &key) {
|
||||
if (secret_.size() == 16) {
|
||||
if (secret_view.size() == 16) {
|
||||
Sha256State state;
|
||||
sha256_init(&state);
|
||||
sha256_update(as_slice(key), &state);
|
||||
sha256_update(secret_, &state);
|
||||
sha256_update(secret_view, &state);
|
||||
sha256_final(&state, as_slice(key));
|
||||
}
|
||||
};
|
||||
|
@ -115,6 +115,10 @@ class OldTransport : public IStreamTransport {
|
||||
return TransportType{TransportType::Tcp, 0, ""};
|
||||
}
|
||||
|
||||
bool use_random_padding() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
TransportImpl impl_{false};
|
||||
ChainBufferReader *input_;
|
||||
@ -126,6 +130,7 @@ class ObfuscatedTransport : public IStreamTransport {
|
||||
ObfuscatedTransport(int16 dc_id, std::string secret)
|
||||
: dc_id_(dc_id), secret_(std::move(secret)), impl_(secret_.size() >= 17) {
|
||||
emulate_tls_ = secret_.size() >= 17 && secret_[0] == '\xee';
|
||||
use_random_padding_ = secret_.size() >= 17;
|
||||
}
|
||||
|
||||
Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) override TD_WARN_UNUSED_RESULT;
|
||||
@ -168,11 +173,15 @@ class ObfuscatedTransport : public IStreamTransport {
|
||||
TransportType get_type() const override {
|
||||
return TransportType{TransportType::ObfuscatedTcp, dc_id_, secret_};
|
||||
}
|
||||
bool use_random_padding() const override {
|
||||
return use_random_padding_;
|
||||
}
|
||||
|
||||
private:
|
||||
int16 dc_id_;
|
||||
std::string secret_;
|
||||
bool emulate_tls_{false};
|
||||
bool use_random_padding_{false};
|
||||
bool is_first_tls_packet_{true};
|
||||
std::string header_;
|
||||
TransportImpl impl_;
|
||||
|
@ -158,11 +158,10 @@ std::pair<uint32, UInt128> Transport::calc_message_key2(const AuthKey &auth_key,
|
||||
return std::make_pair(as<uint32>(msg_key_large_raw) | (1u << 31), res);
|
||||
}
|
||||
|
||||
template <class HeaderT>
|
||||
size_t Transport::calc_crypto_size2(size_t data_size) {
|
||||
size_t enc_size = HeaderT::encrypted_header_size();
|
||||
size_t raw_size = sizeof(HeaderT) - enc_size;
|
||||
namespace {
|
||||
size_t do_calc_crypto_size2_basic(size_t data_size, size_t enc_size, size_t raw_size) {
|
||||
size_t encrypted_size = (enc_size + data_size + 12 + 15) & ~15;
|
||||
|
||||
std::array<size_t, 10> sizes{{64, 128, 192, 256, 384, 512, 768, 1024, 1280}};
|
||||
for (auto size : sizes) {
|
||||
if (encrypted_size <= size) {
|
||||
@ -174,6 +173,29 @@ size_t Transport::calc_crypto_size2(size_t data_size) {
|
||||
return raw_size + encrypted_size;
|
||||
}
|
||||
|
||||
size_t do_calc_crypto_size2_rand(size_t data_size, size_t enc_size, size_t raw_size) {
|
||||
size_t rand_data_size = td::Random::secure_uint32() & 0xff;
|
||||
size_t encrypted_size = (enc_size + data_size + rand_data_size + 12 + 15) & ~15;
|
||||
return raw_size + encrypted_size;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <class HeaderT>
|
||||
size_t Transport::calc_crypto_size2(size_t data_size, PacketInfo *info) {
|
||||
if (info->size != 0) {
|
||||
return info->size;
|
||||
}
|
||||
|
||||
size_t enc_size = HeaderT::encrypted_header_size();
|
||||
size_t raw_size = sizeof(HeaderT) - enc_size;
|
||||
if (info->use_random_padding) {
|
||||
info->size = narrow_cast<uint32>(do_calc_crypto_size2_rand(data_size, enc_size, raw_size));
|
||||
} else {
|
||||
info->size = narrow_cast<uint32>(do_calc_crypto_size2_basic(data_size, enc_size, raw_size));
|
||||
}
|
||||
return info->size;
|
||||
}
|
||||
|
||||
size_t Transport::calc_no_crypto_size(size_t data_size) {
|
||||
return sizeof(NoCryptoHeader) + data_size;
|
||||
}
|
||||
@ -332,7 +354,7 @@ void Transport::write_crypto_impl(int X, const Storer &storer, const AuthKey &au
|
||||
if (info->version == 1) {
|
||||
size = calc_crypto_size<HeaderT>(data_size);
|
||||
} else {
|
||||
size = calc_crypto_size2<HeaderT>(data_size);
|
||||
size = calc_crypto_size2<HeaderT>(data_size, info);
|
||||
}
|
||||
|
||||
size_t pad_size = size - (sizeof(HeaderT) + data_size);
|
||||
@ -365,7 +387,7 @@ size_t Transport::write_crypto(const Storer &storer, const AuthKey &auth_key, Pa
|
||||
if (info->version == 1) {
|
||||
size = calc_crypto_size<CryptoHeader>(data_size);
|
||||
} else {
|
||||
size = calc_crypto_size2<CryptoHeader>(data_size);
|
||||
size = calc_crypto_size2<CryptoHeader>(data_size, info);
|
||||
}
|
||||
if (size > dest.size()) {
|
||||
return size;
|
||||
@ -388,7 +410,7 @@ size_t Transport::write_e2e_crypto(const Storer &storer, const AuthKey &auth_key
|
||||
if (info->version == 1) {
|
||||
size = calc_crypto_size<EndToEndHeader>(data_size);
|
||||
} else {
|
||||
size = calc_crypto_size2<EndToEndHeader>(data_size);
|
||||
size = calc_crypto_size2<EndToEndHeader>(data_size, info);
|
||||
}
|
||||
if (size > dest.size()) {
|
||||
return size;
|
||||
|
@ -97,7 +97,7 @@ class Transport {
|
||||
static size_t calc_crypto_size(size_t data_size);
|
||||
|
||||
template <class HeaderT>
|
||||
static size_t calc_crypto_size2(size_t data_size);
|
||||
static size_t calc_crypto_size2(size_t data_size, PacketInfo *info);
|
||||
|
||||
static size_t calc_no_crypto_size(size_t data_size);
|
||||
|
||||
|
Reference in New Issue
Block a user