Add tests for storage encrypted file.

Also fix some bugs found by the tests.
This commit is contained in:
John Preston 2018-07-28 13:50:28 +03:00
parent 8a371b9c1b
commit 81731139e9
14 changed files with 202 additions and 31 deletions

View file

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "platform/win/windows_dlls.h"
#include <QtCore/QSysInfo>
namespace Platform {
namespace Dlls {
@ -69,10 +71,6 @@ void start() {
load(LibShell32, "SHChangeNotify", SHChangeNotify);
load(LibShell32, "SetCurrentProcessExplicitAppUserModelID", SetCurrentProcessExplicitAppUserModelID);
if (cBetaVersion() == 10020001 && SHChangeNotify) { // Temp - app icon was changed
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
}
LibUxTheme = LoadLibrary(L"UXTHEME.DLL");
load(LibUxTheme, "SetWindowTheme", SetWindowTheme);

View file

@ -28,12 +28,12 @@ File::Result File::open(
const QString &path,
Mode mode,
const EncryptionKey &key) {
close();
_data.setFileName(QFileInfo(path).absoluteFilePath());
const auto result = attemptOpen(mode, key);
if (result != Result::Success) {
_state = base::none;
_data.close();
_lock.unlock();
close();
}
return result;
@ -198,4 +198,12 @@ size_type File::write(bytes::span bytes) {
return count;
}
void File::close() {
_lock.unlock();
_data.close();
_data.setFileName(QString());
_offset = 0;
_state = base::none;
}
} // namespace Storage

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_file_lock.h"
#include "storage/storage_encryption.h"
#include "base/bytes.h"
#include "base/optional.h"
namespace Storage {
@ -31,6 +32,8 @@ public:
size_type read(bytes::span bytes);
size_type write(bytes::span bytes);
void close();
private:
enum class Format : uint32 {
Format_0,

View file

@ -0,0 +1,70 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "catch.hpp"
#include "storage/storage_encrypted_file.h"
const auto key = Storage::EncryptionKey(bytes::make_vector(
bytes::make_span("\
abcdefgh01234567abcdefgh01234567abcdefgh01234567abcdefgh01234567\
abcdefgh01234567abcdefgh01234567abcdefgh01234567abcdefgh01234567\
abcdefgh01234567abcdefgh01234567abcdefgh01234567abcdefgh01234567\
abcdefgh01234567abcdefgh01234567abcdefgh01234567abcdefgh01234567\
").subspan(0, Storage::EncryptionKey::kSize)));
TEST_CASE("simple encrypted file", "[storage_encrypted_file]") {
const auto name = QString("simple.test");
const auto test = bytes::make_span("testbytetestbyte").subspan(0, 16);
SECTION("writing file") {
Storage::File file;
const auto result = file.open(
name,
Storage::File::Mode::Write,
key);
REQUIRE(result == Storage::File::Result::Success);
auto data = bytes::make_vector(test);
const auto written = file.write(data);
REQUIRE(written == data.size());
}
SECTION("reading and writing file") {
Storage::File file;
const auto result = file.open(
name,
Storage::File::Mode::ReadAppend,
key);
REQUIRE(result == Storage::File::Result::Success);
auto data = bytes::vector(16);
const auto read = file.read(data);
REQUIRE(read == data.size());
REQUIRE(data == bytes::make_vector(test));
const auto written = file.write(data);
REQUIRE(written == data.size());
}
SECTION("reading file") {
Storage::File file;
const auto result = file.open(
name,
Storage::File::Mode::Read,
key);
REQUIRE(result == Storage::File::Result::Success);
auto data = bytes::vector(32);
const auto read = file.read(data);
REQUIRE(read == data.size());
REQUIRE(data == bytes::concatenate(test, test));
}
}
TEST_CASE("two process encrypted file", "[storage_encrypted_file]") {
}

View file

@ -30,25 +30,47 @@ void CtrState::process(bytes::span data, index_type offset, Method method) {
_key.size() * CHAR_BIT,
&aes);
unsigned char ecountBuf[kBlockSize];
unsigned int blockNumber = offset / kBlockSize;
unsigned char ecountBuf[kBlockSize] = { 0 };
unsigned int offsetInBlock = 0;
const auto blockIndex = offset / kBlockSize;
auto iv = incrementedIv(blockIndex);
CRYPTO_ctr128_encrypt(
reinterpret_cast<const uchar*>(data.data()),
reinterpret_cast<uchar*>(data.data()),
data.size(),
&aes,
reinterpret_cast<unsigned char*>(_iv.data()),
reinterpret_cast<unsigned char*>(iv.data()),
ecountBuf,
&blockNumber,
&offsetInBlock,
(block128_f)method);
}
auto CtrState::incrementedIv(index_type blockIndex)
-> bytes::array<kIvSize> {
Expects(blockIndex >= 0);
if (!blockIndex) {
return _iv;
}
auto result = _iv;
auto digits = kIvSize;
auto increment = uint64(blockIndex);
do {
--digits;
increment += static_cast<uint64>(result[digits]);
result[digits] = static_cast<bytes::type>(increment & 0xFFULL);
increment >>= 8;
} while (digits != 0 && increment != 0);
return result;
}
void CtrState::encrypt(bytes::span data, index_type offset) {
return process(data, offset, AES_encrypt);
}
void CtrState::decrypt(bytes::span data, index_type offset) {
return process(data, offset, AES_decrypt);
return process(data, offset, AES_encrypt);
}
EncryptionKey::EncryptionKey(bytes::vector &&data)

View file

@ -28,6 +28,8 @@ private:
template <typename Method>
void process(bytes::span data, index_type offset, Method method);
bytes::array<kIvSize> incrementedIv(index_type blockIndex);
static constexpr auto EcountSize = kBlockSize;
bytes::array<kKeySize> _key;

View file

@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "core/basic_types.h"
#include <QtCore/QFile>
namespace Storage {
class FileLock {

View file

@ -71,6 +71,9 @@ FileLock::Lock::Result FileLock::Lock::Acquire(const QFile &file) {
}
}
FileLock::Lock::Lock(int descriptor) : _descriptor(descriptor) {
}
FileLock::Lock::~Lock() {
struct flock unlock;
unlock.l_type = F_UNLCK;

View file

@ -61,6 +61,7 @@
'telegram_win.gypi',
'telegram_mac.gypi',
'telegram_linux.gypi',
'openssl.gypi',
'qt.gypi',
'qt_moc.gypi',
'qt_rcc.gypi',

View file

@ -13,6 +13,7 @@
'type': 'static_library',
'includes': [
'common.gypi',
'openssl.gypi',
'qt.gypi',
'telegram_win.gypi',
'telegram_mac.gypi',

55
Telegram/gyp/openssl.gypi Normal file
View file

@ -0,0 +1,55 @@
# This file is part of Telegram Desktop,
# the official desktop application for the Telegram messaging service.
#
# For license and copyright information please follow this link:
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
{
'conditions': [
[ 'build_win', {
'libraries': [
'-llibeay32',
'-lssleay32',
'-lCrypt32',
],
'configurations': {
'Debug': {
'include_dirs': [
'<(libs_loc)/openssl/Debug/include',
],
'library_dirs': [
'<(libs_loc)/openssl/Debug/lib',
],
},
'Release': {
'include_dirs': [
'<(libs_loc)/openssl/Release/include',
],
'library_dirs': [
'<(libs_loc)/openssl/Release/lib',
],
},
},
}], [ 'build_macold', {
'xcode_settings': {
'OTHER_LDFLAGS': [
'<(libs_loc)/macold/openssl/libssl.a',
'<(libs_loc)/macold/openssl/libcrypto.a',
],
},
'include_dirs': [
'<(libs_loc)/macold/openssl/include',
],
}], [ 'build_mac', {
'xcode_settings': {
'OTHER_LDFLAGS': [
'<(libs_loc)/openssl/libssl.a',
'<(libs_loc)/openssl/libcrypto.a',
],
},
'include_dirs': [
'<(libs_loc)/openssl/include',
],
}],
],
}

View file

@ -55,14 +55,11 @@
'/usr/local/macold/lib/libexif.a',
'/usr/local/macold/lib/libc++.a',
'/usr/local/macold/lib/libc++abi.a',
'<(libs_loc)/macold/openssl/libssl.a',
'<(libs_loc)/macold/openssl/libcrypto.a',
],
},
'include_dirs': [
'/usr/local/macold',
'/usr/local/macold/include/c++/v1',
'<(libs_loc)/macold/openssl/include',
'<(libs_loc)/macold/libexif-0.6.20',
'<(libs_loc)/macold/crashpad',
'<(libs_loc)/macold/crashpad/third_party/mini_chromium/mini_chromium',
@ -122,14 +119,11 @@
'/usr/local/lib/libavutil.a',
'/usr/local/lib/libswscale.a',
'/usr/local/lib/libswresample.a',
'<(libs_loc)/openssl/libssl.a',
'<(libs_loc)/openssl/libcrypto.a',
],
},
'include_dirs': [
'<(libs_loc)/crashpad',
'<(libs_loc)/crashpad/third_party/mini_chromium/mini_chromium',
'<(libs_loc)/openssl/include'
],
'configurations': {
'Debug': {

View file

@ -14,9 +14,6 @@
'<(libs_loc)/ffmpeg',
],
'libraries': [
'-llibeay32',
'-lssleay32',
'-lCrypt32',
'-lzlibstat',
'-lLzmaLib',
'-lUxTheme',
@ -41,11 +38,7 @@
},
'configurations': {
'Debug': {
'include_dirs': [
'<(libs_loc)/openssl/Debug/include',
],
'library_dirs': [
'<(libs_loc)/openssl/Debug/lib',
'<(libs_loc)/lzma/C/Util/LzmaLib/Debug',
'<(libs_loc)/opus/win32/VS2015/Win32/Debug',
'<(libs_loc)/openal-soft/build/Debug',
@ -54,11 +47,7 @@
],
},
'Release': {
'include_dirs': [
'<(libs_loc)/openssl/Release/include',
],
'library_dirs': [
'<(libs_loc)/openssl/Release/lib',
'<(libs_loc)/lzma/C/Util/LzmaLib/Release',
'<(libs_loc)/opus/win32/VS2015/Win32/Release',
'<(libs_loc)/openal-soft/build/Release',

View file

@ -23,6 +23,7 @@
],
'dependencies': [
'<!@(<(list_tests_command))',
'tests_storage',
],
'sources': [
'<!@(<(list_tests_command) --sources)',
@ -116,5 +117,25 @@
'<(src_loc)/rpl/variable.h',
'<(src_loc)/rpl/variable_tests.cpp',
],
}, {
'target_name': 'tests_storage',
'includes': [
'common_test.gypi',
'../openssl.gypi',
],
'dependencies': [
'../lib_storage.gyp:lib_storage',
],
'sources': [
'<(src_loc)/storage/storage_encrypted_file_tests.cpp',
'<(src_loc)/platform/win/windows_dlls.cpp',
'<(src_loc)/platform/win/windows_dlls.h',
],
'conditions': [[ 'not build_win', {
'sources!': [
'<(src_loc)/platform/win/windows_dlls.cpp',
'<(src_loc)/platform/win/windows_dlls.h',
],
}]],
}],
}