Fix secret chat creation.

This commit is contained in:
levlam 2021-07-02 03:25:09 +03:00
parent aeffb5bbff
commit bed2650b4c
3 changed files with 18 additions and 23 deletions

View File

@ -128,7 +128,7 @@ struct NoCryptoHeader {
#endif #endif
#pragma pack(pop) #pragma pack(pop)
// mtproto v1.0 // MTProto v1.0
template <class HeaderT> template <class HeaderT>
std::pair<uint32, UInt128> Transport::calc_message_ack_and_key(const HeaderT &head, size_t data_size) { std::pair<uint32, UInt128> Transport::calc_message_ack_and_key(const HeaderT &head, size_t data_size) {
Slice part(head.encrypt_begin(), head.data + data_size); Slice part(head.encrypt_begin(), head.data + data_size);
@ -144,7 +144,7 @@ size_t Transport::calc_crypto_size(size_t data_size) {
return raw_size + ((enc_size + data_size + 15) & ~15); return raw_size + ((enc_size + data_size + 15) & ~15);
} }
// mtproto v2.0 // MTProto v2.0
std::pair<uint32, UInt128> Transport::calc_message_key2(const AuthKey &auth_key, int X, Slice to_encrypt) { std::pair<uint32, UInt128> Transport::calc_message_key2(const AuthKey &auth_key, int X, Slice to_encrypt) {
// msg_key_large = SHA256 (substr (auth_key, 88+x, 32) + plaintext + random_padding); // msg_key_large = SHA256 (substr (auth_key, 88+x, 32) + plaintext + random_padding);
Sha256State state; Sha256State state;
@ -207,7 +207,7 @@ size_t Transport::calc_no_crypto_size(size_t data_size) {
Status Transport::read_no_crypto(MutableSlice message, PacketInfo *info, MutableSlice *data) { Status Transport::read_no_crypto(MutableSlice message, PacketInfo *info, MutableSlice *data) {
if (message.size() < sizeof(NoCryptoHeader)) { if (message.size() < sizeof(NoCryptoHeader)) {
return Status::Error(PSLICE() << "Invalid mtproto message: too small [message.size() = " << message.size() return Status::Error(PSLICE() << "Invalid MTProto message: too small [message.size() = " << message.size()
<< "] < [sizeof(NoCryptoHeader) = " << sizeof(NoCryptoHeader) << "]"); << "] < [sizeof(NoCryptoHeader) = " << sizeof(NoCryptoHeader) << "]");
} }
size_t data_size = message.size() - sizeof(NoCryptoHeader); size_t data_size = message.size() - sizeof(NoCryptoHeader);
@ -220,7 +220,7 @@ template <class HeaderT, class PrefixT>
Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &auth_key, HeaderT **header_ptr, Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &auth_key, HeaderT **header_ptr,
PrefixT **prefix_ptr, MutableSlice *data, PacketInfo *info) { PrefixT **prefix_ptr, MutableSlice *data, PacketInfo *info) {
if (message.size() < sizeof(HeaderT)) { if (message.size() < sizeof(HeaderT)) {
return Status::Error(PSLICE() << "Invalid mtproto message: too small [message.size() = " << message.size() return Status::Error(PSLICE() << "Invalid MTProto message: too small [message.size() = " << message.size()
<< "] < [sizeof(HeaderT) = " << sizeof(HeaderT) << "]"); << "] < [sizeof(HeaderT) = " << sizeof(HeaderT) << "]");
} }
//FIXME: rewrite without reinterpret cast //FIXME: rewrite without reinterpret cast
@ -230,7 +230,7 @@ Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &a
to_decrypt.remove_suffix(to_decrypt.size() & 15); to_decrypt.remove_suffix(to_decrypt.size() & 15);
if (header->auth_key_id != auth_key.id()) { if (header->auth_key_id != auth_key.id()) {
return Status::Error(PSLICE() << "Invalid mtproto message: auth_key_id mismatch [found = " return Status::Error(PSLICE() << "Invalid MTProto message: auth_key_id mismatch [found = "
<< format::as_hex(header->auth_key_id) << format::as_hex(header->auth_key_id)
<< "] [expected = " << format::as_hex(auth_key.id()) << "]"); << "] [expected = " << format::as_hex(auth_key.id()) << "]");
} }
@ -272,31 +272,31 @@ Status Transport::read_crypto_impl(int X, MutableSlice message, const AuthKey &a
} }
if (!is_key_ok) { if (!is_key_ok) {
return Status::Error(PSLICE() << "Invalid mtproto message: message_key mismatch [found = " return Status::Error(PSLICE() << "Invalid MTProto message: message_key mismatch [found = "
<< format::as_hex_dump(header->message_key) << format::as_hex_dump(header->message_key)
<< "] [expected = " << format::as_hex_dump(real_message_key) << "]"); << "] [expected = " << format::as_hex_dump(real_message_key) << "]");
} }
if (info->version == 2) { if (info->version == 2) {
if (info->check_mod4 && prefix->message_data_length % 4 != 0) { if (info->check_mod4 && prefix->message_data_length % 4 != 0) {
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length (not divisible by four)" return Status::Error(PSLICE() << "Invalid MTProto message: invalid length (not divisible by four)"
<< tag("total_size", message.size()) << tag("total_size", message.size())
<< tag("message_data_length", prefix->message_data_length)); << tag("message_data_length", prefix->message_data_length));
} }
if (tail_size - sizeof(PrefixT) < prefix->message_data_length) { if (tail_size - sizeof(PrefixT) < prefix->message_data_length) {
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length (message_data_length is too big)" return Status::Error(PSLICE() << "Invalid MTProto message: invalid length (message_data_length is too big)"
<< tag("total_size", message.size()) << tag("total_size", message.size())
<< tag("message_data_length", prefix->message_data_length)); << tag("message_data_length", prefix->message_data_length));
} }
size_t pad_size = tail_size - data_size; size_t pad_size = tail_size - data_size;
if (pad_size < 12 || pad_size > 1024) { if (pad_size < 12 || pad_size > 1024) {
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length (invalid padding length)" return Status::Error(PSLICE() << "Invalid MTProto message: invalid length (invalid padding length)"
<< tag("padding_size", pad_size) << tag("total_size", message.size()) << tag("padding_size", pad_size) << tag("total_size", message.size())
<< tag("message_data_length", prefix->message_data_length)); << tag("message_data_length", prefix->message_data_length));
} }
} else { } else {
if (!is_length_ok) { if (!is_length_ok) {
return Status::Error(PSLICE() << "Invalid mtproto message: invalid length " << tag("total_size", message.size()) return Status::Error(PSLICE() << "Invalid MTProto message: invalid length " << tag("total_size", message.size())
<< tag("message_data_length", prefix->message_data_length)); << tag("message_data_length", prefix->message_data_length));
} }
} }
@ -428,7 +428,7 @@ size_t Transport::write_e2e_crypto(const Storer &storer, const AuthKey &auth_key
Result<uint64> Transport::read_auth_key_id(Slice message) { Result<uint64> Transport::read_auth_key_id(Slice message) {
if (message.size() < 8) { if (message.size() < 8) {
return Status::Error(PSLICE() << "Invalid mtproto message: smaller than 8 bytes [size = " << message.size() << "]"); return Status::Error(PSLICE() << "Invalid MTProto message: smaller than 8 bytes [size = " << message.size() << "]");
} }
return as<uint64>(message.begin()); return as<uint64>(message.begin());
} }
@ -436,7 +436,7 @@ Result<uint64> Transport::read_auth_key_id(Slice message) {
Result<Transport::ReadResult> Transport::read(MutableSlice message, const AuthKey &auth_key, PacketInfo *info) { Result<Transport::ReadResult> Transport::read(MutableSlice message, const AuthKey &auth_key, PacketInfo *info) {
if (message.size() < 12) { if (message.size() < 12) {
if (message.size() < 4) { if (message.size() < 4) {
return Status::Error(PSLICE() << "Invalid mtproto message: smaller than 4 bytes [size = " << message.size() return Status::Error(PSLICE() << "Invalid MTProto message: smaller than 4 bytes [size = " << message.size()
<< "]"); << "]");
} }
@ -459,7 +459,7 @@ Result<Transport::ReadResult> Transport::read(MutableSlice message, const AuthKe
TRY_STATUS(read_no_crypto(message, info, &data)); TRY_STATUS(read_no_crypto(message, info, &data));
} else { } else {
if (auth_key.empty()) { if (auth_key.empty()) {
return Status::Error("Failed to decrypt mtproto message: auth key is empty"); return Status::Error("Failed to decrypt MTProto message: auth key is empty");
} }
TRY_STATUS(read_crypto(message, auth_key, info, &data)); TRY_STATUS(read_crypto(message, auth_key, info, &data));
} }

View File

@ -80,10 +80,10 @@ class Transport {
static Result<uint64> read_auth_key_id(Slice message); static Result<uint64> read_auth_key_id(Slice message);
// Reads mtproto packet from [message] and saves into [data]. // Reads MTProto packet from [message] and saves it into [data].
// If message is encrypted, [auth_key] is used. // If message is encrypted, [auth_key] is used.
// Decryption and unpacking is made inplace, so [data] will be subslice of [message]. // Decryption and unpacking is made inplace, so [data] will be subslice of [message].
// Returns size of mtproto packet. // Returns size of MTProto packet.
// If dest.size() >= size, the packet is also written into [dest]. // If dest.size() >= size, the packet is also written into [dest].
// If auth_key is nonempty, encryption will be used. // If auth_key is nonempty, encryption will be used.
static Result<ReadResult> read(MutableSlice message, const AuthKey &auth_key, PacketInfo *info) TD_WARN_UNUSED_RESULT; static Result<ReadResult> read(MutableSlice message, const AuthKey &auth_key, PacketInfo *info) TD_WARN_UNUSED_RESULT;

View File

@ -780,12 +780,7 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
<< tag("crc", crc64(encrypted_message.as_slice()))); << tag("crc", crc64(encrypted_message.as_slice())));
} }
// expect that message is encrypted with mtproto 2.0 if their layer is at least MTPROTO_2_LAYER std::array<int, 2> versions{{2, 1}};
std::array<int, 2> versions{{1, 2}};
if (config_state_.his_layer >= MTPROTO_2_LAYER) {
std::swap(versions[0], versions[1]);
}
BufferSlice encrypted_message_copy; BufferSlice encrypted_message_copy;
int32 mtproto_version = -1; int32 mtproto_version = -1;
Result<mtproto::Transport::ReadResult> r_read_result; Result<mtproto::Transport::ReadResult> r_read_result;
@ -800,7 +795,7 @@ Result<std::tuple<uint64, BufferSlice, int32>> SecretChatActor::decrypt(BufferSl
info.version = mtproto_version; info.version = mtproto_version;
info.is_creator = auth_state_.x == 0; info.is_creator = auth_state_.x == 0;
r_read_result = mtproto::Transport::read(data, *auth_key, &info); r_read_result = mtproto::Transport::read(data, *auth_key, &info);
if (i + 1 == versions.size() && r_read_result.is_error()) { if (i + 1 != versions.size() && r_read_result.is_error()) {
LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error(); LOG(WARNING) << tag("mtproto", mtproto_version) << " decryption failed " << r_read_result.error();
continue; continue;
} }
@ -850,7 +845,7 @@ Status SecretChatActor::do_inbound_message_encrypted(unique_ptr<log_event::Inbou
parser.fetch_end(); parser.fetch_end();
if (!parser.get_error()) { if (!parser.get_error()) {
auto layer = message_with_layer->layer_; auto layer = message_with_layer->layer_;
if (layer < DEFAULT_LAYER && false /* Android app can send such messages */) { if (layer < DEFAULT_LAYER && false /* old Android app could send such messages */) {
LOG(ERROR) << "Layer " << layer << " is not supported, drop message " << to_string(message_with_layer); LOG(ERROR) << "Layer " << layer << " is not supported, drop message " << to_string(message_with_layer);
return Status::OK(); return Status::OK();
} }