Commit 81a309fc authored by Leonid Baraz's avatar Leonid Baraz Committed by Chromium LUCI CQ

Handle signed encryption key file(s).

Writes the key to the file, parses it from the file during
initialization. Encryption is controlled by base::FeatureList;
if encryption is enabled, fail Storage initialization.
Later on we will instead send Upload with no records and
only need_encryption_key flag and reject Enqueue until it is
responded.

Bug: b:170054326
Change-Id: I343b17f9363e11b62e6ab1f69148a7e9e8e0d4c2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2586086Reviewed-by: default avatarZach Trudo <zatrudo@google.com>
Commit-Queue: Leonid Baraz <lbaraz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836807}
parent b90bef2d
......@@ -47,8 +47,14 @@ void AddToRecord(base::StringPiece record,
} // namespace
// static
const char EncryptionModule::kEncryptedReporting[] = "EncryptedReporting";
// static
bool EncryptionModule::is_enabled() {
return base::FeatureList::IsEnabled(kEncryptedReportingFeature);
}
EncryptionModule::EncryptionModule() {
auto encryptor_result = Encryptor::Create();
DCHECK(encryptor_result.ok());
......@@ -60,7 +66,7 @@ EncryptionModule::~EncryptionModule() = default;
void EncryptionModule::EncryptRecord(
base::StringPiece record,
base::OnceCallback<void(StatusOr<EncryptedRecord>)> cb) const {
if (!base::FeatureList::IsEnabled(kEncryptedReportingFeature)) {
if (!is_enabled()) {
// Encryptor disabled.
EncryptedRecord encrypted_record;
encrypted_record.mutable_encrypted_wrapped_record()->assign(record.begin(),
......
......@@ -22,8 +22,8 @@ class EncryptionModule : public base::RefCountedThreadSafe<EncryptionModule> {
// Feature to enable/disable encryption.
// By default encryption is disabled, until server can support decryption.
static const char kEncryptedReporting[];
EncryptionModule();
EncryptionModule();
EncryptionModule(const EncryptionModule& other) = delete;
EncryptionModule& operator=(const EncryptionModule& other) = delete;
......@@ -47,6 +47,10 @@ class EncryptionModule : public base::RefCountedThreadSafe<EncryptionModule> {
// or even changing the key is OK at any time.
bool has_encryption_key() const;
// Returns 'true' if |kEncryptedReporting| feature is enabled.
// To be removed once encryption becomes mandatory.
static bool is_enabled();
protected:
virtual ~EncryptionModule();
......
......@@ -8,6 +8,7 @@
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "base/callback.h"
#include "base/containers/flat_map.h"
......@@ -88,6 +89,9 @@ class Storage : public base::RefCountedThreadSafe<Storage> {
// Private bridge class.
class QueueUploaderInterface;
// Private helper class for key upload/download to the file system.
class KeyInStorage;
// Private constructor, to be called by Create factory method only.
// Queues need to be added afterwards.
Storage(const StorageOptions& options,
......@@ -111,6 +115,9 @@ class Storage : public base::RefCountedThreadSafe<Storage> {
// Encryption module.
scoped_refptr<EncryptionModule> encryption_module_;
// Internal key management module.
std::unique_ptr<KeyInStorage> key_in_storage_;
// Map priority->StorageQueue.
base::flat_map<Priority, scoped_refptr<StorageQueue>> queues_;
......
......@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
......@@ -152,7 +153,7 @@ Status StorageQueue::Init() {
return Status(
error::UNAVAILABLE,
base::StrCat(
{"Fileset directory '", options_.directory().MaybeAsASCII(),
{"Storage queue directory '", options_.directory().MaybeAsASCII(),
"' does not exist, error=", base::File::ErrorToString(error)}));
}
// Enumerate data files and scan the last one to determine what sequence
......
......@@ -13,6 +13,7 @@
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "chrome/browser/policy/messaging_layer/encryption/test_encryption_module.h"
#include "chrome/browser/policy/messaging_layer/storage/storage_configuration.h"
......@@ -234,10 +235,14 @@ class MockUploadClient : public Storage::UploaderInterface {
class StorageTest : public ::testing::TestWithParam<size_t> {
protected:
void SetUp() override { ASSERT_TRUE(location_.CreateUniqueTempDir()); }
void SetUp() override {
ASSERT_TRUE(location_.CreateUniqueTempDir());
// Encryption is disabled.
ASSERT_FALSE(EncryptionModule::is_enabled());
}
void CreateStorageTestOrDie(const StorageOptions& options) {
ASSERT_FALSE(storage_) << "StorageTest already assigned";
StatusOr<scoped_refptr<Storage>> CreateStorageTest(
const StorageOptions& options) {
test_encryption_module_ =
base::MakeRefCounted<test::TestEncryptionModule>();
TestEvent<StatusOr<scoped_refptr<Storage>>> e;
......@@ -245,7 +250,13 @@ class StorageTest : public ::testing::TestWithParam<size_t> {
base::BindRepeating(&StorageTest::BuildMockUploader,
base::Unretained(this)),
test_encryption_module_, e.cb());
StatusOr<scoped_refptr<Storage>> storage_result = e.result();
return e.result();
}
void CreateStorageTestOrDie(const StorageOptions& options) {
ASSERT_FALSE(storage_) << "StorageTest already assigned";
StatusOr<scoped_refptr<Storage>> storage_result =
CreateStorageTest(options);
ASSERT_OK(storage_result)
<< "Failed to create StorageTest, error=" << storage_result.status();
storage_ = std::move(storage_result.ValueOrDie());
......@@ -288,6 +299,8 @@ class StorageTest : public ::testing::TestWithParam<size_t> {
ASSERT_OK(c_result) << c_result;
}
base::test::ScopedFeatureList scoped_feature_list_;
base::ScopedTempDir location_;
scoped_refptr<test::TestEncryptionModule> test_encryption_module_;
scoped_refptr<Storage> storage_;
......@@ -714,6 +727,18 @@ TEST_P(StorageTest, WriteEncryptFailure) {
EXPECT_EQ(result.error_code(), error::UNKNOWN);
}
TEST_P(StorageTest, InitFailureWithNoKey) {
// Enable encryption.
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitFromCommandLine(
{EncryptionModule::kEncryptedReporting}, {});
// TODO(b/170054326): When lack of key file is handled correctly,
// rewrite this test accordingly.
StatusOr<scoped_refptr<Storage>> storage_result =
CreateStorageTest(BuildStorageOptions());
ASSERT_FALSE(storage_result.ok()) << "Storage initialized";
}
INSTANTIATE_TEST_SUITE_P(VaryingFileSize,
StorageTest,
testing::Values(128 * 1024LL * 1024LL,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment