Fix secret chat creation.
This commit is contained in:
parent
aeffb5bbff
commit
bed2650b4c
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user