diff options
author | tbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-31 08:57:34 +0000 |
---|---|---|
committer | tbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-31 08:57:34 +0000 |
commit | 08d758e62cf08b5c12840f4185b858c6925cbe48 (patch) | |
tree | 798b45c60c188be3a9780f0add6116dcfe13f57e | |
parent | c610119714732d73115bad82059d0390f64545d2 (diff) | |
download | chromium_src-08d758e62cf08b5c12840f4185b858c6925cbe48.zip chromium_src-08d758e62cf08b5c12840f4185b858c6925cbe48.tar.gz chromium_src-08d758e62cf08b5c12840f4185b858c6925cbe48.tar.bz2 |
Wire up easy_unlock_private API with the easy-unlock dbus service
BUG=390222
(Note: Needs service_constants update before landing)
Review URL: https://codereview.chromium.org/413933002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@286724 0039d316-1c4b-4281-b951-d872f2087c98
15 files changed, 773 insertions, 7 deletions
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc index 4438d3d..867a4640 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc @@ -5,10 +5,13 @@ #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h" #include "base/bind.h" +#include "base/lazy_instance.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_bluetooth_util.h" +#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h" #include "chrome/common/extensions/api/easy_unlock_private.h" +#include "extensions/browser/browser_context_keyed_api_factory.h" #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -19,6 +22,32 @@ namespace extensions { namespace api { +namespace { + +static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI> > + g_factory = LAZY_INSTANCE_INITIALIZER; + +// Utility method for getting the API's crypto delegate. +EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate( + content::BrowserContext* context) { + return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context) + ->crypto_delegate(); +} + +} // namespace + +// static +BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>* + EasyUnlockPrivateAPI::GetFactoryInstance() { + return g_factory.Pointer(); +} + +EasyUnlockPrivateAPI::EasyUnlockPrivateAPI(content::BrowserContext* context) + : crypto_delegate_(EasyUnlockPrivateCryptoDelegate::Create()) { +} + +EasyUnlockPrivateAPI::~EasyUnlockPrivateAPI() {} + EasyUnlockPrivateGetStringsFunction::EasyUnlockPrivateGetStringsFunction() { } EasyUnlockPrivateGetStringsFunction::~EasyUnlockPrivateGetStringsFunction() { @@ -37,11 +66,11 @@ bool EasyUnlockPrivateGetStringsFunction::RunSync() { "notificationTitle", l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_NOTIFICATION_TITLE, device_type)); - SetResult(strings.release()); return true; } + EasyUnlockPrivatePerformECDHKeyAgreementFunction:: EasyUnlockPrivatePerformECDHKeyAgreementFunction() {} @@ -49,11 +78,21 @@ EasyUnlockPrivatePerformECDHKeyAgreementFunction:: ~EasyUnlockPrivatePerformECDHKeyAgreementFunction() {} bool EasyUnlockPrivatePerformECDHKeyAgreementFunction::RunAsync() { - return false; + scoped_ptr<easy_unlock_private::PerformECDHKeyAgreement::Params> params = + easy_unlock_private::PerformECDHKeyAgreement::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(params); + + GetCryptoDelegate(browser_context())->PerformECDHKeyAgreement( + params->private_key, + params->public_key, + base::Bind(&EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData, + this)); + return true; } void EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData( const std::string& secret_key) { + // TODO(tbarzic): Improve error handling. if (!secret_key.empty()) { results_ = easy_unlock_private::PerformECDHKeyAgreement::Results::Create( secret_key); @@ -68,12 +107,16 @@ EasyUnlockPrivateGenerateEcP256KeyPairFunction:: ~EasyUnlockPrivateGenerateEcP256KeyPairFunction() {} bool EasyUnlockPrivateGenerateEcP256KeyPairFunction::RunAsync() { - return false; + GetCryptoDelegate(browser_context())->GenerateEcP256KeyPair( + base::Bind(&EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData, + this)); + return true; } void EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData( - const std::string& public_key, - const std::string& private_key) { + const std::string& private_key, + const std::string& public_key) { + // TODO(tbarzic): Improve error handling. if (!public_key.empty() && !private_key.empty()) { results_ = easy_unlock_private::GenerateEcP256KeyPair::Results::Create( public_key, private_key); @@ -88,11 +131,29 @@ EasyUnlockPrivateCreateSecureMessageFunction:: ~EasyUnlockPrivateCreateSecureMessageFunction() {} bool EasyUnlockPrivateCreateSecureMessageFunction::RunAsync() { - return false; + scoped_ptr<easy_unlock_private::CreateSecureMessage::Params> params = + easy_unlock_private::CreateSecureMessage::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(params); + + GetCryptoDelegate(browser_context())->CreateSecureMessage( + params->payload, + params->key, + params->options.associated_data ? + *params->options.associated_data : std::string(), + params->options.public_metadata ? + *params->options.public_metadata : std::string(), + params->options.verification_key_id ? + *params->options.verification_key_id : std::string(), + params->options.encrypt_type, + params->options.sign_type, + base::Bind(&EasyUnlockPrivateCreateSecureMessageFunction::OnData, + this)); + return true; } void EasyUnlockPrivateCreateSecureMessageFunction::OnData( const std::string& message) { + // TODO(tbarzic): Improve error handling. if (!message.empty()) { results_ = easy_unlock_private::CreateSecureMessage::Results::Create( message); @@ -107,11 +168,25 @@ EasyUnlockPrivateUnwrapSecureMessageFunction:: ~EasyUnlockPrivateUnwrapSecureMessageFunction() {} bool EasyUnlockPrivateUnwrapSecureMessageFunction::RunAsync() { - return false; + scoped_ptr<easy_unlock_private::UnwrapSecureMessage::Params> params = + easy_unlock_private::UnwrapSecureMessage::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(params); + + GetCryptoDelegate(browser_context())->UnwrapSecureMessage( + params->secure_message, + params->key, + params->options.associated_data ? + *params->options.associated_data : std::string(), + params->options.encrypt_type, + params->options.sign_type, + base::Bind(&EasyUnlockPrivateUnwrapSecureMessageFunction::OnData, + this)); + return true; } void EasyUnlockPrivateUnwrapSecureMessageFunction::OnData( const std::string& data) { + // TODO(tbarzic): Improve error handling. if (!data.empty()) results_ = easy_unlock_private::UnwrapSecureMessage::Results::Create(data); SendResponse(true); diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h index 313ad85..de47c5e 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h @@ -8,10 +8,15 @@ #include <string> #include "base/basictypes.h" +#include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_function.h" // Implementations for chrome.easyUnlockPrivate API functions. +namespace content { +class BrowserContext; +} + namespace extensions { namespace api { @@ -19,6 +24,31 @@ namespace easy_unlock { struct SeekDeviceResult; } // easy_unlock +class EasyUnlockPrivateCryptoDelegate; + +class EasyUnlockPrivateAPI : public BrowserContextKeyedAPI { + public: + static BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>* + GetFactoryInstance(); + + explicit EasyUnlockPrivateAPI(content::BrowserContext* context); + virtual ~EasyUnlockPrivateAPI(); + + EasyUnlockPrivateCryptoDelegate* crypto_delegate() { + return crypto_delegate_.get(); + } + + private: + friend class BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>; + + // BrowserContextKeyedAPI implementation. + static const char* service_name() { return "EasyUnlockPrivate"; } + + scoped_ptr<EasyUnlockPrivateCryptoDelegate> crypto_delegate_; + + DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateAPI); +}; + class EasyUnlockPrivateGetStringsFunction : public SyncExtensionFunction { public: EasyUnlockPrivateGetStringsFunction(); diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h new file mode 100644 index 0000000..5053a99 --- /dev/null +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_CRYPTO_DELEGATE_H_ +#define CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_CRYPTO_DELEGATE_H_ + +#include <string> + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/common/extensions/api/easy_unlock_private.h" + +namespace extensions { +namespace api { + +// Wrapper around EasyUnlock dbus client on ChromeOS. On other platforms, the +// methods are stubbed out. +class EasyUnlockPrivateCryptoDelegate { + public: + typedef base::Callback<void(const std::string& data)> DataCallback; + + typedef base::Callback<void(const std::string& public_key, + const std::string& private_key)> + KeyPairCallback; + + virtual ~EasyUnlockPrivateCryptoDelegate() {} + + // Creates platform specific delegate instance. Non Chrome OS implementations + // currently do nothing but invoke callbacks with empty data. + static scoped_ptr<EasyUnlockPrivateCryptoDelegate> Create(); + + // See chromeos/dbus/easy_unlock_client.h for info on these methods. + virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) = 0; + virtual void PerformECDHKeyAgreement(const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) = 0; + virtual void CreateSecureMessage( + const std::string& payload, + const std::string& secret_key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + easy_unlock_private::EncryptionType encryption_type, + easy_unlock_private::SignatureType signature_type, + const DataCallback& callback) = 0; + virtual void UnwrapSecureMessage( + const std::string& message, + const std::string& secret_key, + const std::string& associated_data, + easy_unlock_private::EncryptionType encryption_type, + easy_unlock_private::SignatureType signature_type, + const DataCallback& callback) = 0; +}; + +} // namespace api +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_CRYPTO_DELEGATE_H_ diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc new file mode 100644 index 0000000..5a18d9e --- /dev/null +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc @@ -0,0 +1,111 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h" + +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/easy_unlock_client.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace extensions { +namespace api { + +namespace { + +// Converts encryption type to a string representation used by EasyUnlock dbus +// client. +std::string EncryptionTypeToString(easy_unlock_private::EncryptionType type) { + switch (type) { + case easy_unlock_private::ENCRYPTION_TYPE_AES_256_CBC: + return easy_unlock::kEncryptionTypeAES256CBC; + default: + return easy_unlock::kEncryptionTypeNone; + } +} + +// Converts signature type to a string representation used by EasyUnlock dbus +// client. +std::string SignatureTypeToString(easy_unlock_private::SignatureType type) { + switch (type) { + case easy_unlock_private::SIGNATURE_TYPE_ECDSA_P256_SHA256: + return easy_unlock::kSignatureTypeECDSAP256SHA256; + case easy_unlock_private::SIGNATURE_TYPE_HMAC_SHA256: + // Fall through to default. + default: + return easy_unlock::kSignatureTypeHMACSHA256; + } +} + +// ChromeOS specific EasyUnlockPrivateCryptoDelegate implementation. +class EasyUnlockPrivateCryptoDelegateChromeOS + : public extensions::api::EasyUnlockPrivateCryptoDelegate { + public: + EasyUnlockPrivateCryptoDelegateChromeOS() + : dbus_client_( + chromeos::DBusThreadManager::Get()->GetEasyUnlockClient()) { + } + + virtual ~EasyUnlockPrivateCryptoDelegateChromeOS() {} + + virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) OVERRIDE { + dbus_client_->GenerateEcP256KeyPair(callback); + } + + virtual void PerformECDHKeyAgreement(const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) OVERRIDE { + dbus_client_->PerformECDHKeyAgreement(private_key, public_key, callback); + } + + virtual void CreateSecureMessage( + const std::string& payload, + const std::string& key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + easy_unlock_private::EncryptionType encryption_type, + easy_unlock_private::SignatureType signature_type, + const DataCallback& callback) OVERRIDE { + dbus_client_->CreateSecureMessage(payload, + key, + associated_data, + public_metadata, + verification_key_id, + EncryptionTypeToString(encryption_type), + SignatureTypeToString(signature_type), + callback); + } + + virtual void UnwrapSecureMessage( + const std::string& message, + const std::string& key, + const std::string& associated_data, + easy_unlock_private::EncryptionType encryption_type, + easy_unlock_private::SignatureType signature_type, + const DataCallback& callback) OVERRIDE { + dbus_client_->UnwrapSecureMessage(message, + key, + associated_data, + EncryptionTypeToString(encryption_type), + SignatureTypeToString(signature_type), + callback); + } + + private: + scoped_ptr<chromeos::EasyUnlockClient> dbus_client_; + + DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateCryptoDelegateChromeOS); +}; + +} // namespace + +// static +scoped_ptr<EasyUnlockPrivateCryptoDelegate> + EasyUnlockPrivateCryptoDelegate::Create() { + return scoped_ptr<EasyUnlockPrivateCryptoDelegate>( + new EasyUnlockPrivateCryptoDelegateChromeOS()); +} + +} // namespace api +} // namespace extensions diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc new file mode 100644 index 0000000..f4b8879d --- /dev/null +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc @@ -0,0 +1,66 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h" + +namespace extensions { +namespace api { + +namespace { + +// Stub EasyUnlockPrivateCryptoDelegate implementation. +class EasyUnlockPrivateCryptoDelegateStub + : public extensions::api::EasyUnlockPrivateCryptoDelegate { + public: + EasyUnlockPrivateCryptoDelegateStub() {} + + virtual ~EasyUnlockPrivateCryptoDelegateStub() {} + + virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) OVERRIDE { + callback.Run("", ""); + } + + virtual void PerformECDHKeyAgreement(const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) OVERRIDE { + callback.Run(""); + } + + virtual void CreateSecureMessage( + const std::string& payload, + const std::string& key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + easy_unlock_private::EncryptionType encryption_type, + easy_unlock_private::SignatureType signature_type, + const DataCallback& callback) OVERRIDE { + callback.Run(""); + } + + virtual void UnwrapSecureMessage( + const std::string& message, + const std::string& key, + const std::string& associated_data, + easy_unlock_private::EncryptionType encryption_type, + easy_unlock_private::SignatureType signature_type, + const DataCallback& callback) OVERRIDE { + callback.Run(""); + } + + private: + DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateCryptoDelegateStub); +}; + +} // namespace + +// static +scoped_ptr<EasyUnlockPrivateCryptoDelegate> + EasyUnlockPrivateCryptoDelegate::Create() { + return scoped_ptr<EasyUnlockPrivateCryptoDelegate>( + new EasyUnlockPrivateCryptoDelegateStub()); +} + +} // namespace api +} // namespace extensions diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index cc3c6c5..3fd3d49 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -325,6 +325,7 @@ 'browser/extensions/updater/local_extension_cache.h', ], 'chrome_browser_extensions_non_chromeos_sources': [ + 'browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc', 'browser/extensions/api/feedback_private/feedback_service_nonchromeos.cc', 'browser/extensions/api/image_writer_private/operation_nonchromeos.cc', 'browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc', @@ -543,6 +544,8 @@ 'browser/extensions/api/easy_unlock_private/easy_unlock_private_bluetooth_util.h', 'browser/extensions/api/easy_unlock_private/easy_unlock_private_bluetooth_util.cc', 'browser/extensions/api/easy_unlock_private/easy_unlock_private_bluetooth_util_chromeos.cc', + 'browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h', + 'browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc', 'browser/extensions/api/execute_code_function.cc', 'browser/extensions/api/execute_code_function.h', 'browser/extensions/api/experience_sampling_private/experience_sampling.cc', diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index da86460..872a782 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -121,6 +121,8 @@ 'dbus/dbus_thread_manager.h', 'dbus/debug_daemon_client.cc', 'dbus/debug_daemon_client.h', + 'dbus/easy_unlock_client.cc', + 'dbus/easy_unlock_client.h', 'dbus/fake_bluetooth_adapter_client.cc', 'dbus/fake_bluetooth_adapter_client.h', 'dbus/fake_bluetooth_agent_manager_client.cc', @@ -155,6 +157,8 @@ 'dbus/fake_dbus_thread_manager.h', 'dbus/fake_debug_daemon_client.cc', 'dbus/fake_debug_daemon_client.h', + 'dbus/fake_easy_unlock_client.cc', + 'dbus/fake_easy_unlock_client.h', 'dbus/fake_gsm_sms_client.cc', 'dbus/fake_gsm_sms_client.h', 'dbus/fake_image_burner_client.cc', diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index 4c57529..e372005 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc @@ -24,6 +24,7 @@ #include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_thread_manager_observer.h" #include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/dbus/fake_dbus_thread_manager.h" #include "chromeos/dbus/gsm_sms_client.h" #include "chromeos/dbus/image_burner_client.h" @@ -80,6 +81,7 @@ class DBusClientBundle { cros_disks_client_.reset(CrosDisksClient::Create(type)); cryptohome_client_.reset(CryptohomeClient::Create()); debug_daemon_client_.reset(DebugDaemonClient::Create()); + easy_unlock_client_.reset(EasyUnlockClient::Create()); lorgnette_manager_client_.reset(LorgnetteManagerClient::Create()); shill_manager_client_.reset(ShillManagerClient::Create()); shill_device_client_.reset(ShillDeviceClient::Create()); @@ -146,6 +148,9 @@ class DBusClientBundle { DebugDaemonClient* debug_daemon_client() { return debug_daemon_client_.get(); } + EasyUnlockClient* easy_unlock_client() { + return easy_unlock_client_.get(); + } LorgnetteManagerClient* lorgnette_manager_client() { return lorgnette_manager_client_.get(); } @@ -225,6 +230,7 @@ class DBusClientBundle { scoped_ptr<CrosDisksClient> cros_disks_client_; scoped_ptr<CryptohomeClient> cryptohome_client_; scoped_ptr<DebugDaemonClient> debug_daemon_client_; + scoped_ptr<EasyUnlockClient> easy_unlock_client_; scoped_ptr<LorgnetteManagerClient> lorgnette_manager_client_; scoped_ptr<ShillDeviceClient> shill_device_client_; scoped_ptr<ShillIPConfigClient> shill_ipconfig_client_; @@ -361,6 +367,9 @@ class DBusThreadManagerImpl : public DBusThreadManager { return client_bundle_->debug_daemon_client(); } + virtual EasyUnlockClient* GetEasyUnlockClient() OVERRIDE { + return client_bundle_->easy_unlock_client(); + } virtual LorgnetteManagerClient* GetLorgnetteManagerClient() OVERRIDE { return client_bundle_->lorgnette_manager_client(); } @@ -580,6 +589,7 @@ void DBusThreadManager::InitializeClients() { InitClient(g_dbus_thread_manager->GetCrosDisksClient()); InitClient(g_dbus_thread_manager->GetCryptohomeClient()); InitClient(g_dbus_thread_manager->GetDebugDaemonClient()); + InitClient(g_dbus_thread_manager->GetEasyUnlockClient()); InitClient(g_dbus_thread_manager->GetGsmSMSClient()); InitClient(g_dbus_thread_manager->GetImageBurnerClient()); InitClient(g_dbus_thread_manager->GetIntrospectableClient()); diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h index ad93a2f..f225a5e 100644 --- a/chromeos/dbus/dbus_thread_manager.h +++ b/chromeos/dbus/dbus_thread_manager.h @@ -38,6 +38,7 @@ class CrosDisksClient; class CryptohomeClient; class DBusClient; class DebugDaemonClient; +class EasyUnlockClient; class GsmSMSClient; class ImageBurnerClient; class IntrospectableClient; @@ -138,6 +139,7 @@ class CHROMEOS_EXPORT DBusThreadManager { virtual CrosDisksClient* GetCrosDisksClient() = 0; virtual CryptohomeClient* GetCryptohomeClient() = 0; virtual DebugDaemonClient* GetDebugDaemonClient() = 0; + virtual EasyUnlockClient* GetEasyUnlockClient() = 0; virtual GsmSMSClient* GetGsmSMSClient() = 0; virtual ImageBurnerClient* GetImageBurnerClient() = 0; virtual IntrospectableClient* GetIntrospectableClient() = 0; diff --git a/chromeos/dbus/easy_unlock_client.cc b/chromeos/dbus/easy_unlock_client.cc new file mode 100644 index 0000000..60040c0 --- /dev/null +++ b/chromeos/dbus/easy_unlock_client.cc @@ -0,0 +1,186 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/dbus/easy_unlock_client.h" + +#include <vector> + +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +namespace { + +// Reads array of bytes from a dbus message reader and converts it to string. +std::string PopResponseData(dbus::MessageReader* reader) { + const uint8* bytes = NULL; + size_t length = 0; + if (!reader->PopArrayOfBytes(&bytes, &length)) + return ""; + + return std::string(reinterpret_cast<const char*>(bytes), length); +} + +// Converts string to array of bytes and writes it using dbus meddage writer. +void AppendStringAsByteArray(const std::string& data, + dbus::MessageWriter* writer) { + writer->AppendArrayOfBytes(reinterpret_cast<const uint8*>(data.data()), + data.length()); +} + +// The EasyUnlockClient used in production (and returned by +// EasyUnlockClient::Create). +class EasyUnlockClientImpl : public EasyUnlockClient { + public: + EasyUnlockClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {} + + virtual ~EasyUnlockClientImpl() {} + + // EasyUnlockClient override. + virtual void PerformECDHKeyAgreement(const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + easy_unlock::kEasyUnlockServiceInterface, + easy_unlock::kPerformECDHKeyAgreementMethod); + dbus::MessageWriter writer(&method_call); + // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is + // not guaranteed here, so the method uses byte arrays. + AppendStringAsByteArray(private_key, &writer); + AppendStringAsByteArray(public_key, &writer); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&EasyUnlockClientImpl::OnData, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // EasyUnlockClient override. + virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + easy_unlock::kEasyUnlockServiceInterface, + easy_unlock::kGenerateEcP256KeyPairMethod); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&EasyUnlockClientImpl::OnKeyPair, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // EasyUnlockClient override. + virtual void CreateSecureMessage(const std::string& payload, + const std::string& secret_key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + easy_unlock::kEasyUnlockServiceInterface, + easy_unlock::kCreateSecureMessageMethod); + dbus::MessageWriter writer(&method_call); + // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is + // not guaranteed here, so the method uses byte arrays. + AppendStringAsByteArray(payload, &writer); + AppendStringAsByteArray(secret_key, &writer); + AppendStringAsByteArray(associated_data, &writer); + AppendStringAsByteArray(public_metadata, &writer); + AppendStringAsByteArray(verification_key_id, &writer); + writer.AppendString(encryption_type); + writer.AppendString(signature_type); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&EasyUnlockClientImpl::OnData, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + // EasyUnlockClient override. + virtual void UnwrapSecureMessage(const std::string& message, + const std::string& secret_key, + const std::string& associated_data, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) OVERRIDE { + dbus::MethodCall method_call( + easy_unlock::kEasyUnlockServiceInterface, + easy_unlock::kUnwrapSecureMessageMethod); + dbus::MessageWriter writer(&method_call); + // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is + // not guaranteed here, so the method uses byte arrays. + AppendStringAsByteArray(message, &writer); + AppendStringAsByteArray(secret_key, &writer); + AppendStringAsByteArray(associated_data, &writer); + writer.AppendString(encryption_type); + writer.AppendString(signature_type); + proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, + base::Bind(&EasyUnlockClientImpl::OnData, + weak_ptr_factory_.GetWeakPtr(), + callback)); + } + + protected: + virtual void Init(dbus::Bus* bus) OVERRIDE { + proxy_ = + bus->GetObjectProxy( + easy_unlock::kEasyUnlockServiceName, + dbus::ObjectPath(easy_unlock::kEasyUnlockServicePath)); + } + + private: + void OnData(const DataCallback& callback, dbus::Response* response) { + if (!response) { + callback.Run(""); + return; + } + + dbus::MessageReader reader(response); + callback.Run(PopResponseData(&reader)); + } + + void OnKeyPair(const KeyPairCallback& callback, dbus::Response* response) { + if (!response) { + callback.Run("", ""); + return; + } + + dbus::MessageReader reader(response); + std::string private_key = PopResponseData(&reader); + std::string public_key = PopResponseData(&reader); + + if (public_key.empty() || private_key.empty()) { + callback.Run("", ""); + return; + } + + callback.Run(private_key, public_key); + } + + dbus::ObjectProxy* proxy_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<EasyUnlockClientImpl> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(EasyUnlockClientImpl); +}; + +} // namespace + +EasyUnlockClient::EasyUnlockClient() { +} + +EasyUnlockClient::~EasyUnlockClient() { +} + +// static +EasyUnlockClient* EasyUnlockClient::Create() { + return new EasyUnlockClientImpl(); +} + +} // namespace chromeos diff --git a/chromeos/dbus/easy_unlock_client.h b/chromeos/dbus/easy_unlock_client.h new file mode 100644 index 0000000..0cbad74b --- /dev/null +++ b/chromeos/dbus/easy_unlock_client.h @@ -0,0 +1,115 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_DBUS_EASY_UNLOCK_CLIENT_H_ +#define CHROMEOS_DBUS_EASY_UNLOCK_CLIENT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "chromeos/chromeos_export.h" +#include "chromeos/dbus/dbus_client.h" + +namespace chromeos { + +// Client for calling EasyUnlock dbus service. The service provides +// methods used by Easy Unlock for establishing secure communication channel +// over (unsecure) bluetooth with devices registered to unlock ChromeOS. +// Ideally, this would be done in Chrome, but unfortunatelly, the library used +// for wrapping and unwrapping messages sent over the communication channel +// depends on OpenSSL for encryption, which is not currently available in +// Chrome. To work around this, the message processing will be done in ChromeOS, +// where OpenSSL is already supported. +// TODO(tbarzic): Get rid of this client when Chrome switches from NSS to +// OpenSSL (http://crbug.com/338888). +class CHROMEOS_EXPORT EasyUnlockClient : public DBusClient { + public: + virtual ~EasyUnlockClient(); + + typedef base::Callback<void(const std::string& data)> DataCallback; + + // Callback for |GenerateEcP256KeyAgreement|. Carries the generated keys. + typedef base::Callback<void(const std::string& public_key, + const std::string& private_key)> + KeyPairCallback; + + // Generates ECDSA key pair using P256 curve. + // The created keys should only be used with this client. + virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) = 0; + + // Given a private and a public key, creates a symetric secret key using + // EC Diffe-Hellman key exchange. The provided keys come from different + // asymetric key pairs, and are expected to be in the same format as the ones + // returned by |GenerateEcP256KeyAgreement|. Reversing key pairs from which + // private and public key come generates the same secret key. + virtual void PerformECDHKeyAgreement(const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) = 0; + + // Creates signed and, if specified, encrypted message in format used by Easy + // Unlock. + // |payload|: The cleartext message body. + // |key|: The key used to sign, and if needed, encrypt the message. If + // encryption is required, the key must be symetric. + // |associated_data|: Data associated with the message. The data will not + // actually be added to the message, but it will be used while + // signing the message (the receiver will use the same data to + // authenticate the signature). + // |public_metadata|: Metadata added to the message header. + // |verification_key_id|: The key id added to the message header. Has to be + // set if the message is signed with private asymetric key. This value + // is used by the receiver to identify the public key that should be used + // to verify the signature. + // |encryption_type|: The encryption algorithm to use for encrypting the + // message. (May be set to none). + // |signature_type|: The algorithm to use to sign the message. + // |callback|: Called with the created message. On failure, the message will + // be empty. + virtual void CreateSecureMessage(const std::string& payload, + const std::string& secret_key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) = 0; + + // Authenticates and, if specified, decrypts a secure message. + // |message|: The message to unwrap. It is in the same format as the message + // returned by |CreateSecureMessage|. + // |key|: The key used to authenticate message signature and, if needed, + // decrypt the message. If the message is encrypted, only symetric key + // can be used. + // |associated_data|: Data associated with the message. Message + // authentication will succeed only if the message was created with the + // associated data. + // |encryption_type|: The encryption algorithm to use for decrypting the + // message. (May be set to none). + // |signature_type|: The algorithm to use to verify the message signature. + // |callback|: Called with the cleartext message header and body in a signle + // protobuf. If the message could not be authenticated or decrypted, it + // will be called with an empty string. + virtual void UnwrapSecureMessage(const std::string& message, + const std::string& secret_key, + const std::string& associated_data, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) = 0; + + // Factory function, creates a new instance and returns ownership. + // For normal usage, access the singleton via DBusThreadManager::Get(). + static EasyUnlockClient* Create(); + + protected: + // Create() should be used instead. + EasyUnlockClient(); + + private: + DISALLOW_COPY_AND_ASSIGN(EasyUnlockClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_EASY_UNLOCK_CLIENT_H_ diff --git a/chromeos/dbus/fake_dbus_thread_manager.cc b/chromeos/dbus/fake_dbus_thread_manager.cc index 3839b0a..38e67e3 100644 --- a/chromeos/dbus/fake_dbus_thread_manager.cc +++ b/chromeos/dbus/fake_dbus_thread_manager.cc @@ -22,6 +22,7 @@ #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/fake_easy_unlock_client.h" #include "chromeos/dbus/fake_gsm_sms_client.h" #include "chromeos/dbus/fake_image_burner_client.h" #include "chromeos/dbus/fake_introspectable_client.h" @@ -83,6 +84,7 @@ void FakeDBusThreadManager::SetFakeClients() { SetCryptohomeClient(scoped_ptr<CryptohomeClient>(new FakeCryptohomeClient)); SetDebugDaemonClient( scoped_ptr<DebugDaemonClient>(new FakeDebugDaemonClient)); + SetEasyUnlockClient(scoped_ptr<EasyUnlockClient>(new FakeEasyUnlockClient)); SetLorgnetteManagerClient( scoped_ptr<LorgnetteManagerClient>(new FakeLorgnetteManagerClient)); @@ -205,6 +207,11 @@ void FakeDBusThreadManager::SetDebugDaemonClient( debug_daemon_client_ = client.Pass(); } +void FakeDBusThreadManager::SetEasyUnlockClient( + scoped_ptr<EasyUnlockClient> client) { + easy_unlock_client_ = client.Pass(); +} + void FakeDBusThreadManager::SetLorgnetteManagerClient( scoped_ptr<LorgnetteManagerClient> client) { lorgnette_manager_client_ = client.Pass(); @@ -385,6 +392,9 @@ DebugDaemonClient* FakeDBusThreadManager::GetDebugDaemonClient() { return debug_daemon_client_.get(); } +EasyUnlockClient* FakeDBusThreadManager::GetEasyUnlockClient() { + return easy_unlock_client_.get(); +} LorgnetteManagerClient* FakeDBusThreadManager::GetLorgnetteManagerClient() { return lorgnette_manager_client_.get(); } diff --git a/chromeos/dbus/fake_dbus_thread_manager.h b/chromeos/dbus/fake_dbus_thread_manager.h index 87a9ba5c..075b906 100644 --- a/chromeos/dbus/fake_dbus_thread_manager.h +++ b/chromeos/dbus/fake_dbus_thread_manager.h @@ -54,6 +54,7 @@ class CHROMEOS_EXPORT FakeDBusThreadManager : public DBusThreadManager { void SetCrosDisksClient(scoped_ptr<CrosDisksClient> client); void SetCryptohomeClient(scoped_ptr<CryptohomeClient> client); void SetDebugDaemonClient(scoped_ptr<DebugDaemonClient> client); + void SetEasyUnlockClient(scoped_ptr<EasyUnlockClient> client); void SetLorgnetteManagerClient(scoped_ptr<LorgnetteManagerClient> client); void SetShillDeviceClient(scoped_ptr<ShillDeviceClient> client); void SetShillIPConfigClient(scoped_ptr<ShillIPConfigClient> client); @@ -98,6 +99,7 @@ class CHROMEOS_EXPORT FakeDBusThreadManager : public DBusThreadManager { virtual CrosDisksClient* GetCrosDisksClient() OVERRIDE; virtual CryptohomeClient* GetCryptohomeClient() OVERRIDE; virtual DebugDaemonClient* GetDebugDaemonClient() OVERRIDE; + virtual EasyUnlockClient* GetEasyUnlockClient() OVERRIDE; virtual LorgnetteManagerClient* GetLorgnetteManagerClient() OVERRIDE; virtual ShillDeviceClient* GetShillDeviceClient() OVERRIDE; virtual ShillIPConfigClient* GetShillIPConfigClient() OVERRIDE; @@ -141,6 +143,7 @@ class CHROMEOS_EXPORT FakeDBusThreadManager : public DBusThreadManager { scoped_ptr<CrosDisksClient> cros_disks_client_; scoped_ptr<CryptohomeClient> cryptohome_client_; scoped_ptr<DebugDaemonClient> debug_daemon_client_; + scoped_ptr<EasyUnlockClient> easy_unlock_client_; scoped_ptr<LorgnetteManagerClient> lorgnette_manager_client_; scoped_ptr<ShillDeviceClient> shill_device_client_; scoped_ptr<ShillIPConfigClient> shill_ipconfig_client_; diff --git a/chromeos/dbus/fake_easy_unlock_client.cc b/chromeos/dbus/fake_easy_unlock_client.cc new file mode 100644 index 0000000..748c0e6 --- /dev/null +++ b/chromeos/dbus/fake_easy_unlock_client.cc @@ -0,0 +1,45 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/dbus/fake_easy_unlock_client.h" + +namespace chromeos { + +FakeEasyUnlockClient::FakeEasyUnlockClient() {} + +FakeEasyUnlockClient::~FakeEasyUnlockClient() {} + +void FakeEasyUnlockClient::Init(dbus::Bus* bus) {} + +void FakeEasyUnlockClient::GenerateEcP256KeyPair( + const KeyPairCallback& callback) { +} + +void FakeEasyUnlockClient::PerformECDHKeyAgreement( + const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) { +} + +void FakeEasyUnlockClient::CreateSecureMessage( + const std::string& payload, + const std::string& secret_key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) { +} + +void FakeEasyUnlockClient::UnwrapSecureMessage( + const std::string& message, + const std::string& secret_key, + const std::string& associated_data, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) { +} + +} // namespace chromeos diff --git a/chromeos/dbus/fake_easy_unlock_client.h b/chromeos/dbus/fake_easy_unlock_client.h new file mode 100644 index 0000000..ddb0b92 --- /dev/null +++ b/chromeos/dbus/fake_easy_unlock_client.h @@ -0,0 +1,47 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_DBUS_FAKE_EASY_UNLOCK_CLIENT_H_ +#define CHROMEOS_DBUS_FAKE_EASY_UNLOCK_CLIENT_H_ + +#include <string> + +#include "chromeos/dbus/easy_unlock_client.h" + +namespace chromeos { + +// A fake implemetation of EasyUnlockClient. +class CHROMEOS_EXPORT FakeEasyUnlockClient : public EasyUnlockClient { + public: + FakeEasyUnlockClient(); + virtual ~FakeEasyUnlockClient(); + + // EasyUnlockClient overrides + virtual void Init(dbus::Bus* bus) OVERRIDE; + virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) OVERRIDE; + virtual void PerformECDHKeyAgreement(const std::string& private_key, + const std::string& public_key, + const DataCallback& callback) OVERRIDE; + virtual void CreateSecureMessage(const std::string& payload, + const std::string& secret_key, + const std::string& associated_data, + const std::string& public_metadata, + const std::string& verification_key_id, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) OVERRIDE; + virtual void UnwrapSecureMessage(const std::string& message, + const std::string& secret_key, + const std::string& associated_data, + const std::string& encryption_type, + const std::string& signature_type, + const DataCallback& callback) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(FakeEasyUnlockClient); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FAKE_EASY_UNLOCK_CLIENT_H_ |