diff options
author | Alex Vakulenko <avakulenko@google.com> | 2015-10-08 07:34:23 -0700 |
---|---|---|
committer | Alex Vakulenko <avakulenko@google.com> | 2015-10-08 07:44:57 -0700 |
commit | df38164c0c7bfef18b68d3ba5be9a516bf6198de (patch) | |
tree | 7f7e0d0546b87bbf20991c2f3b93eeb6d7bea529 | |
parent | 2915a7b9a45821a7530d2fea8a982bc1b6efc7d3 (diff) | |
download | weaved-df38164c0c7bfef18b68d3ba5be9a516bf6198de.tar.gz |
Removing mnc-brillo-dev specific changes to weaved
Moved recent changes to weaved from Brillo branch to AOSP and used
conditional compilation to compile Brillo-specific code on Brillo only.
This eliminates differences in source files for the branch and future
code merge issues.
Change-Id: I355a1022cb0d31ea1ab7e0c476824ebbad1af43c
-rw-r--r-- | Android.mk | 16 | ||||
-rw-r--r-- | buffet/buffet_config.cc | 59 | ||||
-rw-r--r-- | buffet/buffet_config.h | 31 | ||||
-rw-r--r-- | buffet/buffet_config_unittest.cc | 81 | ||||
-rw-r--r-- | buffet/encryptor.h | 53 | ||||
-rw-r--r-- | buffet/fake_encryptor.cc | 41 | ||||
-rw-r--r-- | buffet/keystore_encryptor.cc | 51 | ||||
-rw-r--r-- | buffet/keystore_encryptor.h | 46 |
8 files changed, 375 insertions, 3 deletions
@@ -48,6 +48,14 @@ buffetSharedLibraries := \ libweave \ libwebserv \ +ifdef BRILLO + +buffetSharedLibraries += \ + libkeymaster_messages \ + libkeystore_binder \ + +endif + # buffet-common # ======================================================== include $(CLEAR_VARS) @@ -80,6 +88,13 @@ LOCAL_SRC_FILES := \ buffet/dbus_bindings/com.android.Weave.Command.dbus-xml \ buffet/dbus_bindings/com.android.Weave.Manager.dbus-xml \ +ifdef BRILLO +LOCAL_SRC_FILES += buffet/keystore_encryptor.cc +else +LOCAL_SRC_FILES += buffet/fake_encryptor.cc +endif + + include $(BUILD_STATIC_LIBRARY) # buffet @@ -146,6 +161,7 @@ LOCAL_RTTI_FLAG := -frtti LOCAL_CLANG := true LOCAL_SRC_FILES := \ + buffet/buffet_config_unittest.cc \ buffet/buffet_testrunner.cc \ buffet/dbus_command_proxy_unittest.cc \ buffet/dbus_conversion_unittest.cc \ diff --git a/buffet/buffet_config.cc b/buffet/buffet_config.cc index fde6f0e..c375e1f 100644 --- a/buffet/buffet_config.cc +++ b/buffet/buffet_config.cc @@ -18,6 +18,24 @@ namespace buffet { +namespace { + +const char kErrorDomain[] = "buffet"; +const char kFileReadError[] = "file_read_error"; + +class DefaultFileIO : public BuffetConfig::FileIO { + public: + bool ReadFile(const base::FilePath& path, std::string* content) override { + return base::ReadFileToString(path, content); + } + bool WriteFile(const base::FilePath& path, + const std::string& content) override { + return base::ImportantFileWriter::WriteFileAtomically(path, content); + } +}; + +} // namespace + namespace config_keys { const char kClientId[] = "client_id"; @@ -40,7 +58,12 @@ const char kPairingModes[] = "pairing_modes"; } // namespace config_keys -BuffetConfig::BuffetConfig(const Options& options) : options_(options) {} +BuffetConfig::BuffetConfig(const Options& options) + : options_(options), + default_encryptor_(Encryptor::CreateDefaultEncryptor()), + encryptor_(default_encryptor_.get()), + default_file_io_(new DefaultFileIO), + file_io_(default_file_io_.get()) {} bool BuffetConfig::LoadDefaults(weave::Settings* settings) { // Keep this hardcoded default for sometime. This previously was set by @@ -132,13 +155,43 @@ bool BuffetConfig::LoadDefaults(const chromeos::KeyValueStore& store, } std::string BuffetConfig::LoadSettings() { + std::string settings_blob; + if (!file_io_->ReadFile(options_.settings, &settings_blob)) { + LOG(WARNING) << "Failed to read settings, proceeding with empty settings."; + return std::string(); + } std::string json_string; - base::ReadFileToString(options_.settings, &json_string); + if (!encryptor_->DecryptWithAuthentication(settings_blob, &json_string)) { + LOG(WARNING) + << "Failed to decrypt settings, proceeding with empty settings."; + SaveSettings(std::string()); + return std::string(); + } return json_string; } void BuffetConfig::SaveSettings(const std::string& settings) { - base::ImportantFileWriter::WriteFileAtomically(options_.settings, settings); + std::string encrypted_settings; + if (!encryptor_->EncryptWithAuthentication(settings, &encrypted_settings)) { + LOG(ERROR) << "Failed to encrypt settings, writing empty settings."; + encrypted_settings.clear(); + } + if (!file_io_->WriteFile(options_.settings, encrypted_settings)) { + LOG(ERROR) << "Failed to write settings."; + } +} + +bool BuffetConfig::LoadFile(const base::FilePath& file_path, + std::string* data, + chromeos::ErrorPtr* error) { + if (!file_io_->ReadFile(file_path, data)) { + chromeos::errors::system::AddSystemError(error, FROM_HERE, errno); + chromeos::Error::AddToPrintf(error, FROM_HERE, kErrorDomain, kFileReadError, + "Failed to read file '%s'", + file_path.value().c_str()); + return false; + } + return true; } } // namespace buffet diff --git a/buffet/buffet_config.h b/buffet/buffet_config.h index a286bf8..3db6de8 100644 --- a/buffet/buffet_config.h +++ b/buffet/buffet_config.h @@ -12,9 +12,12 @@ #include <base/callback.h> #include <base/files/file_path.h> +#include <chromeos/errors/error.h> #include <chromeos/key_value_store.h> #include <weave/provider/config_store.h> +#include "buffet/encryptor.h" + namespace buffet { class StorageInterface; @@ -39,6 +42,14 @@ class BuffetConfig final : public weave::provider::ConfigStore { std::string test_privet_ssid; }; + // An IO abstraction to enable testing without using real files. + class FileIO { + public: + virtual bool ReadFile(const base::FilePath& path, std::string* content) = 0; + virtual bool WriteFile(const base::FilePath& path, + const std::string& content) = 0; + }; + ~BuffetConfig() override = default; explicit BuffetConfig(const Options& options); @@ -51,8 +62,28 @@ class BuffetConfig final : public weave::provider::ConfigStore { bool LoadDefaults(const chromeos::KeyValueStore& store, weave::Settings* settings); + // Allows injection of a non-default |encryptor| for testing. The caller + // retains ownership of the pointer. + void SetEncryptor(Encryptor* encryptor) { + encryptor_ = encryptor; + } + + // Allows injection of non-default |file_io| for testing. The caller retains + // ownership of the pointer. + void SetFileIO(FileIO* file_io) { + file_io_ = file_io; + } + private: + bool LoadFile(const base::FilePath& file_path, + std::string* data, + chromeos::ErrorPtr* error); + Options options_; + std::unique_ptr<Encryptor> default_encryptor_; + Encryptor* encryptor_{nullptr}; + std::unique_ptr<FileIO> default_file_io_; + FileIO* file_io_{nullptr}; DISALLOW_COPY_AND_ASSIGN(BuffetConfig); }; diff --git a/buffet/buffet_config_unittest.cc b/buffet/buffet_config_unittest.cc index 58c2117..795d172 100644 --- a/buffet/buffet_config_unittest.cc +++ b/buffet/buffet_config_unittest.cc @@ -7,6 +7,7 @@ #include <set> #include <base/bind.h> +#include <chromeos/data_encoding.h> #include <gtest/gtest.h> namespace buffet { @@ -66,4 +67,84 @@ TEST(BuffetConfigTest, LoadConfig) { EXPECT_FALSE(settings.local_discovery_enabled); } +class BuffetConfigTestWithFakes : public testing::Test, + public BuffetConfig::FileIO, + public Encryptor { + public: + void SetUp() { + BuffetConfig::Options config_options; + config_options.settings = base::FilePath{"settings_file"}; + config_.reset(new BuffetConfig{config_options}); + config_->SetEncryptor(this); + config_->SetFileIO(this); + }; + + // buffet::Encryptor methods. + bool EncryptWithAuthentication(const std::string& plaintext, + std::string* ciphertext) override { + *ciphertext = chromeos::data_encoding::Base64Encode(plaintext); + return encryptor_result_; + }; + bool DecryptWithAuthentication(const std::string& ciphertext, + std::string* plaintext) override { + return encryptor_result_ && + chromeos::data_encoding::Base64Decode(ciphertext, plaintext); + }; + + // buffet::BuffetConfig::FileIO methods. + bool ReadFile(const base::FilePath& path, std::string* content) override { + if (fake_file_content_.count(path.value()) == 0) { + return false; + } + *content = fake_file_content_[path.value()]; + return io_result_; + }; + bool WriteFile(const base::FilePath& path, + const std::string& content) override { + if (io_result_) { + fake_file_content_[path.value()] = content; + } + return io_result_; + }; + + protected: + std::map<std::string, std::string> fake_file_content_; + bool encryptor_result_ = true; + bool io_result_ = true; + std::unique_ptr<BuffetConfig> config_; +}; + +TEST_F(BuffetConfigTestWithFakes, EncryptionEnabled) { + config_->SaveSettings("test"); + ASSERT_NE("test", fake_file_content_["settings_file"]); + ASSERT_EQ("test", config_->LoadSettings()); +} + +TEST_F(BuffetConfigTestWithFakes, EncryptionFailure) { + config_->SaveSettings("test"); + ASSERT_FALSE(fake_file_content_["settings_file"].empty()); + encryptor_result_ = false; + config_->SaveSettings("test2"); + // Encryption fails -> file cleared. + ASSERT_TRUE(fake_file_content_["settings_file"].empty()); +} + +TEST_F(BuffetConfigTestWithFakes, DecryptionFailure) { + config_->SaveSettings("test"); + ASSERT_FALSE(fake_file_content_["settings_file"].empty()); + encryptor_result_ = false; + // Decryption fails -> empty settings loaded. + ASSERT_TRUE(config_->LoadSettings().empty()); +} + +TEST_F(BuffetConfigTestWithFakes, SettingsIOFailure) { + config_->SaveSettings("test"); + std::string original = fake_file_content_["settings_file"]; + ASSERT_FALSE(original.empty()); + io_result_ = false; + ASSERT_TRUE(config_->LoadSettings().empty()); + config_->SaveSettings("test2"); + ASSERT_EQ(original, fake_file_content_["settings_file"]); +} + } // namespace buffet diff --git a/buffet/encryptor.h b/buffet/encryptor.h new file mode 100644 index 0000000..96f4f71 --- /dev/null +++ b/buffet/encryptor.h @@ -0,0 +1,53 @@ +// Copyright 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BUFFET_ENCRYPTOR_H_ +#define BUFFET_ENCRYPTOR_H_ + +#include <memory> +#include <string> + +#include <base/macros.h> + +namespace buffet { + +// An abstract class to perform authenticated encryption. +class Encryptor { + public: + Encryptor() = default; + virtual ~Encryptor() = default; + + // Encrypts and authenticates the given |plaintext| and emits the + // |ciphertext|. Returns true on success. + virtual bool EncryptWithAuthentication(const std::string& plaintext, + std::string* ciphertext) = 0; + + // Decrypts and authenticates the given |ciphertext| and emits the + // |plaintext|. Returns true on success. + virtual bool DecryptWithAuthentication(const std::string& ciphertext, + std::string* plaintext) = 0; + + // A factory method to be exported by the default Encryptor implementation + // for a given platform. Like a constructor, this method should not perform + // any significant initialization work. The caller assumes ownership of the + // pointer. + static std::unique_ptr<Encryptor> CreateDefaultEncryptor(); + + private: + DISALLOW_COPY_AND_ASSIGN(Encryptor); +}; + +} // namespace buffet + +#endif // BUFFET_ENCRYPTOR_H_ diff --git a/buffet/fake_encryptor.cc b/buffet/fake_encryptor.cc new file mode 100644 index 0000000..b82b9f0 --- /dev/null +++ b/buffet/fake_encryptor.cc @@ -0,0 +1,41 @@ +// Copyright 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "buffet/encryptor.h" + +#include <memory> + +#include <chromeos/data_encoding.h> + +namespace buffet { + +class FakeEncryptor : public Encryptor { + public: + bool EncryptWithAuthentication(const std::string& plaintext, + std::string* ciphertext) override { + *ciphertext = chromeos::data_encoding::Base64Encode(plaintext); + return true; + } + + bool DecryptWithAuthentication(const std::string& ciphertext, + std::string* plaintext) override { + return chromeos::data_encoding::Base64Decode(ciphertext, plaintext); + } +}; + +std::unique_ptr<Encryptor> Encryptor::CreateDefaultEncryptor() { + return std::unique_ptr<Encryptor>{new FakeEncryptor}; +} + +} // namespace buffet diff --git a/buffet/keystore_encryptor.cc b/buffet/keystore_encryptor.cc new file mode 100644 index 0000000..e4a5c82 --- /dev/null +++ b/buffet/keystore_encryptor.cc @@ -0,0 +1,51 @@ +// Copyright 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "buffet/keystore_encryptor.h" + +#include <memory> + +#include <keystore/keystore_client_impl.h> + +namespace { + +const char kBuffetKeyName[] = "buffet_config_b4f594c3"; + +} // namespace + +namespace buffet { + +std::unique_ptr<Encryptor> Encryptor::CreateDefaultEncryptor() { + return std::unique_ptr<Encryptor>( + new KeystoreEncryptor(std::unique_ptr<keystore::KeystoreClient>( + new keystore::KeystoreClientImpl))); +} + +KeystoreEncryptor::KeystoreEncryptor( + std::unique_ptr<keystore::KeystoreClient> keystore) + : keystore_(std::move(keystore)) {} + +bool KeystoreEncryptor::EncryptWithAuthentication(const std::string& plaintext, + std::string* ciphertext) { + return keystore_->encryptWithAuthentication(kBuffetKeyName, plaintext, + ciphertext); +} + +bool KeystoreEncryptor::DecryptWithAuthentication(const std::string& ciphertext, + std::string* plaintext) { + return keystore_->decryptWithAuthentication(kBuffetKeyName, ciphertext, + plaintext); +} + +} // namespace buffet diff --git a/buffet/keystore_encryptor.h b/buffet/keystore_encryptor.h new file mode 100644 index 0000000..ec2294b --- /dev/null +++ b/buffet/keystore_encryptor.h @@ -0,0 +1,46 @@ +// Copyright 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BUFFET_KEYSTORE_ENCRYPTOR_H_ +#define BUFFET_KEYSTORE_ENCRYPTOR_H_ + +#include "buffet/encryptor.h" + +#include <memory> + +#include <keystore/keystore_client.h> + +namespace buffet { + +// An Encryptor implementation backed by Brillo Keystore. This class is intended +// to be the default encryptor on platforms that support it. An implementation +// of Encryptor::CreateDefaultEncryptor is provided for this class. +class KeystoreEncryptor : public Encryptor { + public: + explicit KeystoreEncryptor( + std::unique_ptr<keystore::KeystoreClient> keystore); + ~KeystoreEncryptor() override = default; + + bool EncryptWithAuthentication(const std::string& plaintext, + std::string* ciphertext) override; + bool DecryptWithAuthentication(const std::string& ciphertext, + std::string* plaintext) override; + + private: + std::unique_ptr<keystore::KeystoreClient> keystore_; +}; + +} // namespace buffet + +#endif // BUFFET_KEYSTORE_ENCRYPTOR_H_ |