diff --git a/CMakeLists.txt b/CMakeLists.txt index ca4d16314..4603576ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -482,6 +482,7 @@ set(TDLIB_SOURCE td/telegram/files/FileBitmask.h td/telegram/files/FileDb.h td/telegram/files/FileDownloader.h + td/telegram/files/FileEncryptionKey.h td/telegram/files/FileFromBytes.h td/telegram/files/FileGcParameters.h td/telegram/files/FileGcWorker.h diff --git a/td/telegram/files/FileEncryptionKey.h b/td/telegram/files/FileEncryptionKey.h new file mode 100644 index 000000000..4e83d1235 --- /dev/null +++ b/td/telegram/files/FileEncryptionKey.h @@ -0,0 +1,155 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// 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/telegram/SecureStorage.h" + +#include "td/utils/as.h" +#include "td/utils/common.h" +#include "td/utils/crypto.h" +#include "td/utils/logging.h" +#include "td/utils/Random.h" +#include "td/utils/Slice.h" +#include "td/utils/StringBuilder.h" +#include "td/utils/tl_helpers.h" +#include "td/utils/UInt.h" + +namespace td { + +struct FileEncryptionKey { + enum class Type : int32 { None, Secret, Secure }; + FileEncryptionKey() = default; + FileEncryptionKey(Slice key, Slice iv) : key_iv_(key.size() + iv.size(), '\0'), type_(Type::Secret) { + if (key.size() != 32 || iv.size() != 32) { + LOG(ERROR) << "Wrong key/iv sizes: " << key.size() << " " << iv.size(); + type_ = Type::None; + return; + } + CHECK(key_iv_.size() == 64); + MutableSlice(key_iv_).copy_from(key); + MutableSlice(key_iv_).substr(key.size()).copy_from(iv); + } + + explicit FileEncryptionKey(const secure_storage::Secret &secret) : type_(Type::Secure) { + key_iv_ = secret.as_slice().str(); + } + + bool is_secret() const { + return type_ == Type::Secret; + } + bool is_secure() const { + return type_ == Type::Secure; + } + + static FileEncryptionKey create() { + FileEncryptionKey res; + res.key_iv_.resize(64); + Random::secure_bytes(res.key_iv_); + res.type_ = Type::Secret; + return res; + } + static FileEncryptionKey create_secure_key() { + return FileEncryptionKey(secure_storage::Secret::create_new()); + } + + const UInt256 &key() const { + CHECK(is_secret()); + CHECK(key_iv_.size() == 64); + return *reinterpret_cast(key_iv_.data()); + } + Slice key_slice() const { + CHECK(is_secret()); + CHECK(key_iv_.size() == 64); + return Slice(key_iv_.data(), 32); + } + secure_storage::Secret secret() const { + CHECK(is_secure()); + return secure_storage::Secret::create(Slice(key_iv_).truncate(32)).move_as_ok(); + } + + bool has_value_hash() const { + CHECK(is_secure()); + return key_iv_.size() > secure_storage::Secret::size(); + } + + void set_value_hash(const secure_storage::ValueHash &value_hash) { + key_iv_.resize(secure_storage::Secret::size() + value_hash.as_slice().size()); + MutableSlice(key_iv_).remove_prefix(secure_storage::Secret::size()).copy_from(value_hash.as_slice()); + } + + secure_storage::ValueHash value_hash() const { + CHECK(has_value_hash()); + return secure_storage::ValueHash::create(Slice(key_iv_).remove_prefix(secure_storage::Secret::size())).move_as_ok(); + } + + UInt256 &mutable_iv() { + CHECK(is_secret()); + CHECK(key_iv_.size() == 64); + return *reinterpret_cast(&key_iv_[0] + 32); + } + Slice iv_slice() const { + CHECK(is_secret()); + CHECK(key_iv_.size() == 64); + return Slice(key_iv_.data() + 32, 32); + } + + int32 calc_fingerprint() const { + CHECK(is_secret()); + char buf[16]; + md5(key_iv_, {buf, sizeof(buf)}); + return as(buf) ^ as(buf + 4); + } + + bool empty() const { + return key_iv_.empty(); + } + size_t size() const { + return key_iv_.size(); + } + + template + void store(StorerT &storer) const { + td::store(key_iv_, storer); + } + template + void parse(Type type, ParserT &parser) { + td::parse(key_iv_, parser); + if (key_iv_.empty()) { + type_ = Type::None; + } else { + if (type_ == Type::Secure) { + if (key_iv_.size() != 64) { + LOG(ERROR) << "Have wrong key size " << key_iv_.size(); + } + } + type_ = type; + } + } + + string key_iv_; // TODO wrong alignment is possible + Type type_ = Type::None; +}; + +inline bool operator==(const FileEncryptionKey &lhs, const FileEncryptionKey &rhs) { + return lhs.key_iv_ == rhs.key_iv_; +} + +inline bool operator!=(const FileEncryptionKey &lhs, const FileEncryptionKey &rhs) { + return !(lhs == rhs); +} + +inline StringBuilder &operator<<(StringBuilder &string_builder, const FileEncryptionKey &key) { + if (key.is_secret()) { + return string_builder << "SecretKey{" << key.size() << "}"; + } + if (key.is_secret()) { + return string_builder << "SecureKey{" << key.size() << "}"; + } + return string_builder << "NoKey{}"; +} + +} // namespace td diff --git a/td/telegram/files/FileHashUploader.cpp b/td/telegram/files/FileHashUploader.cpp index 7aae6b2ae..a66d2f44d 100644 --- a/td/telegram/files/FileHashUploader.cpp +++ b/td/telegram/files/FileHashUploader.cpp @@ -23,6 +23,7 @@ #include "td/utils/Status.h" namespace td { + void FileHashUploader::start_up() { auto status = init(); if (status.is_error()) { @@ -31,6 +32,7 @@ void FileHashUploader::start_up() { return; } } + Status FileHashUploader::init() { TRY_RESULT(fd, FileFd::open(local_.path_, FileFd::Read)); if (fd.get_size() != size_) { @@ -43,6 +45,7 @@ Status FileHashUploader::init() { resource_state_.update_estimated_limit(size_); return Status::OK(); } + void FileHashUploader::loop() { if (stop_flag_) { return; @@ -140,4 +143,5 @@ Status FileHashUploader::on_result_impl(NetQueryPtr net_query) { return Status::Error("UNREACHABLE"); } } + } // namespace td diff --git a/td/telegram/files/FileHashUploader.h b/td/telegram/files/FileHashUploader.h index 81d0f0d8c..922965da2 100644 --- a/td/telegram/files/FileHashUploader.h +++ b/td/telegram/files/FileHashUploader.h @@ -79,4 +79,5 @@ class FileHashUploader : public FileLoaderActor { Status on_result_impl(NetQueryPtr net_query); }; + } // namespace td diff --git a/td/telegram/files/FileLocation.h b/td/telegram/files/FileLocation.h index 67bd63199..ed71e54d1 100644 --- a/td/telegram/files/FileLocation.h +++ b/td/telegram/files/FileLocation.h @@ -11,22 +11,17 @@ #include "td/telegram/DialogId.h" #include "td/telegram/files/FileBitmask.h" +#include "td/telegram/files/FileEncryptionKey.h" #include "td/telegram/net/DcId.h" -#include "td/telegram/SecureStorage.h" -#include "td/utils/as.h" #include "td/utils/buffer.h" #include "td/utils/common.h" -#include "td/utils/crypto.h" #include "td/utils/format.h" -#include "td/utils/int_types.h" #include "td/utils/logging.h" -#include "td/utils/Random.h" #include "td/utils/Slice.h" #include "td/utils/StringBuilder.h" #include "td/utils/tl_helpers.h" #include "td/utils/tl_storers.h" -#include "td/utils/UInt.h" #include "td/utils/Variant.h" #include @@ -178,138 +173,6 @@ inline bool is_file_big(FileType file_type, int64 expected_size) { return expected_size > SMALL_FILE_MAX_SIZE; } -struct FileEncryptionKey { - enum class Type : int32 { None, Secret, Secure }; - FileEncryptionKey() = default; - FileEncryptionKey(Slice key, Slice iv) : key_iv_(key.size() + iv.size(), '\0'), type_(Type::Secret) { - if (key.size() != 32 || iv.size() != 32) { - LOG(ERROR) << "Wrong key/iv sizes: " << key.size() << " " << iv.size(); - type_ = Type::None; - return; - } - CHECK(key_iv_.size() == 64); - MutableSlice(key_iv_).copy_from(key); - MutableSlice(key_iv_).substr(key.size()).copy_from(iv); - } - - explicit FileEncryptionKey(const secure_storage::Secret &secret) : type_(Type::Secure) { - key_iv_ = secret.as_slice().str(); - } - - bool is_secret() const { - return type_ == Type::Secret; - } - bool is_secure() const { - return type_ == Type::Secure; - } - - static FileEncryptionKey create() { - FileEncryptionKey res; - res.key_iv_.resize(64); - Random::secure_bytes(res.key_iv_); - res.type_ = Type::Secret; - return res; - } - static FileEncryptionKey create_secure_key() { - return FileEncryptionKey(secure_storage::Secret::create_new()); - } - - const UInt256 &key() const { - CHECK(is_secret()); - CHECK(key_iv_.size() == 64); - return *reinterpret_cast(key_iv_.data()); - } - Slice key_slice() const { - CHECK(is_secret()); - CHECK(key_iv_.size() == 64); - return Slice(key_iv_.data(), 32); - } - secure_storage::Secret secret() const { - CHECK(is_secure()); - return secure_storage::Secret::create(Slice(key_iv_).truncate(32)).move_as_ok(); - } - - bool has_value_hash() const { - CHECK(is_secure()); - return key_iv_.size() > secure_storage::Secret::size(); - } - - void set_value_hash(const secure_storage::ValueHash &value_hash) { - key_iv_.resize(secure_storage::Secret::size() + value_hash.as_slice().size()); - MutableSlice(key_iv_).remove_prefix(secure_storage::Secret::size()).copy_from(value_hash.as_slice()); - } - - secure_storage::ValueHash value_hash() const { - CHECK(has_value_hash()); - return secure_storage::ValueHash::create(Slice(key_iv_).remove_prefix(secure_storage::Secret::size())).move_as_ok(); - } - - UInt256 &mutable_iv() { - CHECK(is_secret()); - CHECK(key_iv_.size() == 64); - return *reinterpret_cast(&key_iv_[0] + 32); - } - Slice iv_slice() const { - CHECK(is_secret()); - CHECK(key_iv_.size() == 64); - return Slice(key_iv_.data() + 32, 32); - } - - int32 calc_fingerprint() const { - CHECK(is_secret()); - char buf[16]; - md5(key_iv_, {buf, sizeof(buf)}); - return as(buf) ^ as(buf + 4); - } - - bool empty() const { - return key_iv_.empty(); - } - size_t size() const { - return key_iv_.size(); - } - - template - void store(StorerT &storer) const { - td::store(key_iv_, storer); - } - template - void parse(Type type, ParserT &parser) { - td::parse(key_iv_, parser); - if (key_iv_.empty()) { - type_ = Type::None; - } else { - if (type_ == Type::Secure) { - if (key_iv_.size() != 64) { - LOG(ERROR) << "Have wrong key size " << key_iv_.size(); - } - } - type_ = type; - } - } - - string key_iv_; // TODO wrong alignment is possible - Type type_ = Type::None; -}; - -inline bool operator==(const FileEncryptionKey &lhs, const FileEncryptionKey &rhs) { - return lhs.key_iv_ == rhs.key_iv_; -} - -inline bool operator!=(const FileEncryptionKey &lhs, const FileEncryptionKey &rhs) { - return !(lhs == rhs); -} - -inline StringBuilder &operator<<(StringBuilder &string_builder, const FileEncryptionKey &key) { - if (key.is_secret()) { - return string_builder << "SecretKey{" << key.size() << "}"; - } - if (key.is_secret()) { - return string_builder << "SecureKey{" << key.size() << "}"; - } - return string_builder << "NoKey{}"; -} - struct EmptyRemoteFileLocation { template void store(StorerT &storer) const {