Add FileEncryptionKey.h.
GitOrigin-RevId: e21c5ae48403835fb910e55545b64d6edf4f6651
This commit is contained in:
parent
86bf606666
commit
4c5c2422d3
@ -482,6 +482,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/files/FileBitmask.h
|
td/telegram/files/FileBitmask.h
|
||||||
td/telegram/files/FileDb.h
|
td/telegram/files/FileDb.h
|
||||||
td/telegram/files/FileDownloader.h
|
td/telegram/files/FileDownloader.h
|
||||||
|
td/telegram/files/FileEncryptionKey.h
|
||||||
td/telegram/files/FileFromBytes.h
|
td/telegram/files/FileFromBytes.h
|
||||||
td/telegram/files/FileGcParameters.h
|
td/telegram/files/FileGcParameters.h
|
||||||
td/telegram/files/FileGcWorker.h
|
td/telegram/files/FileGcWorker.h
|
||||||
|
155
td/telegram/files/FileEncryptionKey.h
Normal file
155
td/telegram/files/FileEncryptionKey.h
Normal file
@ -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<const UInt256 *>(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<UInt256 *>(&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<int32>(buf) ^ as<int32>(buf + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return key_iv_.empty();
|
||||||
|
}
|
||||||
|
size_t size() const {
|
||||||
|
return key_iv_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class StorerT>
|
||||||
|
void store(StorerT &storer) const {
|
||||||
|
td::store(key_iv_, storer);
|
||||||
|
}
|
||||||
|
template <class ParserT>
|
||||||
|
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
|
@ -23,6 +23,7 @@
|
|||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
void FileHashUploader::start_up() {
|
void FileHashUploader::start_up() {
|
||||||
auto status = init();
|
auto status = init();
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
@ -31,6 +32,7 @@ void FileHashUploader::start_up() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status FileHashUploader::init() {
|
Status FileHashUploader::init() {
|
||||||
TRY_RESULT(fd, FileFd::open(local_.path_, FileFd::Read));
|
TRY_RESULT(fd, FileFd::open(local_.path_, FileFd::Read));
|
||||||
if (fd.get_size() != size_) {
|
if (fd.get_size() != size_) {
|
||||||
@ -43,6 +45,7 @@ Status FileHashUploader::init() {
|
|||||||
resource_state_.update_estimated_limit(size_);
|
resource_state_.update_estimated_limit(size_);
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileHashUploader::loop() {
|
void FileHashUploader::loop() {
|
||||||
if (stop_flag_) {
|
if (stop_flag_) {
|
||||||
return;
|
return;
|
||||||
@ -140,4 +143,5 @@ Status FileHashUploader::on_result_impl(NetQueryPtr net_query) {
|
|||||||
return Status::Error("UNREACHABLE");
|
return Status::Error("UNREACHABLE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -79,4 +79,5 @@ class FileHashUploader : public FileLoaderActor {
|
|||||||
|
|
||||||
Status on_result_impl(NetQueryPtr net_query);
|
Status on_result_impl(NetQueryPtr net_query);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -11,22 +11,17 @@
|
|||||||
|
|
||||||
#include "td/telegram/DialogId.h"
|
#include "td/telegram/DialogId.h"
|
||||||
#include "td/telegram/files/FileBitmask.h"
|
#include "td/telegram/files/FileBitmask.h"
|
||||||
|
#include "td/telegram/files/FileEncryptionKey.h"
|
||||||
#include "td/telegram/net/DcId.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/buffer.h"
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/crypto.h"
|
|
||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/int_types.h"
|
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/Random.h"
|
|
||||||
#include "td/utils/Slice.h"
|
#include "td/utils/Slice.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
#include "td/utils/tl_helpers.h"
|
#include "td/utils/tl_helpers.h"
|
||||||
#include "td/utils/tl_storers.h"
|
#include "td/utils/tl_storers.h"
|
||||||
#include "td/utils/UInt.h"
|
|
||||||
#include "td/utils/Variant.h"
|
#include "td/utils/Variant.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
@ -178,138 +173,6 @@ inline bool is_file_big(FileType file_type, int64 expected_size) {
|
|||||||
return expected_size > SMALL_FILE_MAX_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<const UInt256 *>(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<UInt256 *>(&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<int32>(buf) ^ as<int32>(buf + 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const {
|
|
||||||
return key_iv_.empty();
|
|
||||||
}
|
|
||||||
size_t size() const {
|
|
||||||
return key_iv_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class StorerT>
|
|
||||||
void store(StorerT &storer) const {
|
|
||||||
td::store(key_iv_, storer);
|
|
||||||
}
|
|
||||||
template <class ParserT>
|
|
||||||
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 {
|
struct EmptyRemoteFileLocation {
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
|
Loading…
Reference in New Issue
Block a user