diff options
20 files changed, 572 insertions, 32 deletions
@@ -128,6 +128,10 @@ 'chromeos': { 'filepath': 'chromeos/', }, + 'chromeos_attestation': { + 'filepath': 'chromeos/attestation/|'\ + 'chrome/browser/chromeos/attestation/', + }, 'chromeos_calculator': { 'filepath': 'chrome/common/extensions/docs/examples/apps/calculator/', }, @@ -569,6 +573,7 @@ 'chromedriver': ['kkania@chromium.org'], 'chromeos' : ['oshima+watch@chromium.org', 'stevenjb+watch@chromium.org'], + 'chromeos_attestation' : ['dkrahn+watch@chromium.org'], 'chromeos_calculator' : ['dharcourt@chromium.org'], 'chromeos_net' : ['gauravsh+watch@chromium.org', 'gspencer+watch@chromium.org', diff --git a/chrome/browser/chromeos/attestation/OWNERS b/chrome/browser/chromeos/attestation/OWNERS new file mode 100644 index 0000000..cd1c574 --- /dev/null +++ b/chrome/browser/chromeos/attestation/OWNERS @@ -0,0 +1,2 @@ +mnissler@chromium.org +pastarmovj@chromium.org diff --git a/chrome/browser/chromeos/attestation/attestation_ca_client.cc b/chrome/browser/chromeos/attestation/attestation_ca_client.cc new file mode 100644 index 0000000..74e89bd --- /dev/null +++ b/chrome/browser/chromeos/attestation/attestation_ca_client.cc @@ -0,0 +1,31 @@ +// Copyright (c) 2013 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/chromeos/attestation/attestation_ca_client.h" + +#include <string> + +#include "base/bind.h" +#include "base/message_loop.h" + +namespace chromeos { +namespace attestation { + +AttestationCAClient::AttestationCAClient() {} + +AttestationCAClient::~AttestationCAClient() {} + +void AttestationCAClient::SendEnrollRequest(const std::string& request, + const DataCallback& on_response) { + NOTIMPLEMENTED(); +} + +void AttestationCAClient::SendCertificateRequest( + const std::string& request, + const DataCallback& on_response) { + NOTIMPLEMENTED(); +} + +} // namespace attestation +} // namespace chromeos diff --git a/chrome/browser/chromeos/attestation/attestation_ca_client.h b/chrome/browser/chromeos/attestation/attestation_ca_client.h new file mode 100644 index 0000000..8c5a676 --- /dev/null +++ b/chrome/browser/chromeos/attestation/attestation_ca_client.h @@ -0,0 +1,37 @@ +// Copyright (c) 2013 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_CHROMEOS_ATTESTATION_ATTESTATION_CA_CLIENT_H_ +#define CHROME_BROWSER_CHROMEOS_ATTESTATION_ATTESTATION_CA_CLIENT_H_ + +#include <string> + +#include "base/basictypes.h" + +#include "chromeos/attestation/attestation_flow.h" + +namespace chromeos { +namespace attestation { + +// This class is a ServerProxy implementation for the Chrome OS attestation +// flow. It sends all requests to an Attestation CA via HTTPS. +class AttestationCAClient : public ServerProxy { + public: + AttestationCAClient(); + virtual ~AttestationCAClient(); + + // chromeos::attestation::ServerProxy: + virtual void SendEnrollRequest(const std::string& request, + const DataCallback& on_response) OVERRIDE; + virtual void SendCertificateRequest(const std::string& request, + const DataCallback& on_response) OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(AttestationCAClient); +}; + +} // namespace attestation +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_ATTESTATION_ATTESTATION_CA_CLIENT_H_ diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc new file mode 100644 index 0000000..21664cd --- /dev/null +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc @@ -0,0 +1,187 @@ +// Copyright (c) 2013 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/chromeos/attestation/attestation_policy_observer.h" + +#include <string> + +#include "base/bind.h" +#include "chrome/browser/chromeos/attestation/attestation_ca_client.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/policy/cloud/cloud_policy_client.h" +#include "chrome/browser/policy/cloud/cloud_policy_manager.h" +#include "chrome/common/chrome_notification_types.h" +#include "chromeos/attestation/attestation_flow.h" +#include "chromeos/cryptohome/async_method_caller.h" +#include "chromeos/dbus/cryptohome_client.h" +#include "chromeos/dbus/dbus_method_call_status.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_details.h" + +namespace { + +// A dbus callback which handles a boolean result. +// +// Parameters +// on_true - Called when status=success and value=true. +// on_false - Called when status=success and value=false. +// status - The dbus operation status. +// value - The value returned by the dbus operation. +void DBusBoolRedirectCallback(const base::Closure& on_true, + const base::Closure& on_false, + chromeos::DBusMethodCallStatus status, + bool value) { + if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) + return; + const base::Closure& task = value ? on_true : on_false; + if (!task.is_null()) + task.Run(); +} + +// A dbus callback which handles a string result. +// +// Parameters +// on_success - Called when status=success and result=true. +// status - The dbus operation status. +// result - The result returned by the dbus operation. +// data - The data returned by the dbus operation. +void DBusStringCallback( + const base::Callback<void(const std::string&)> on_success, + chromeos::DBusMethodCallStatus status, + bool result, + const std::string& data) { + if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) + return; + on_success.Run(data); +} + +} // namespace + +namespace chromeos { +namespace attestation { + +const char AttestationPolicyObserver::kEnterpriseMachineKey[] = + "attest-ent-machine"; + +AttestationPolicyObserver::AttestationPolicyObserver( + policy::CloudPolicyClient* policy_client) + : cros_settings_(CrosSettings::Get()), + policy_client_(policy_client), + cryptohome_client_(NULL), + attestation_flow_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); + Start(); +} + +AttestationPolicyObserver::AttestationPolicyObserver( + policy::CloudPolicyClient* policy_client, + CryptohomeClient* cryptohome_client, + AttestationFlow* attestation_flow) + : cros_settings_(CrosSettings::Get()), + policy_client_(policy_client), + cryptohome_client_(cryptohome_client), + attestation_flow_(attestation_flow), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); + Start(); +} + +AttestationPolicyObserver::~AttestationPolicyObserver() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + cros_settings_->RemoveSettingsObserver(kDeviceAttestationEnabled, this); +} + +void AttestationPolicyObserver::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + std::string* path = content::Details<std::string>(details).ptr(); + if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED || + *path != kDeviceAttestationEnabled) { + LOG(WARNING) << "AttestationPolicyObserver: Unexpected event received."; + return; + } + Start(); +} + +void AttestationPolicyObserver::Start() { + // If attestation is not enabled, there is nothing to do. + bool enabled = false; + if (!cros_settings_->GetBoolean(kDeviceAttestationEnabled, &enabled) || + !enabled) + return; + + // We expect a registered CloudPolicyClient. + if (!policy_client_->is_registered()) { + LOG(ERROR) << "AttestationPolicyObserver: Invalid CloudPolicyClient."; + return; + } + + if (!cryptohome_client_) + cryptohome_client_ = DBusThreadManager::Get()->GetCryptohomeClient(); + + if (!attestation_flow_) { + scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); + default_attestation_flow_.reset(new AttestationFlow( + cryptohome::AsyncMethodCaller::GetInstance(), + cryptohome_client_, + attestation_ca_client.Pass())); + attestation_flow_ = default_attestation_flow_.get(); + } + + // Start a dbus call to check if an Enterprise Machine Key already exists. + base::Closure on_does_exist = + base::Bind(&AttestationPolicyObserver::GetExistingCertificate, + weak_factory_.GetWeakPtr()); + base::Closure on_does_not_exist = + base::Bind(&AttestationPolicyObserver::GetNewCertificate, + weak_factory_.GetWeakPtr()); + cryptohome_client_->TpmAttestationDoesKeyExist( + CryptohomeClient::DEVICE_KEY, + kEnterpriseMachineKey, + base::Bind(DBusBoolRedirectCallback, on_does_exist, on_does_not_exist)); +} + +void AttestationPolicyObserver::GetNewCertificate() { + // We can reuse the dbus callback handler logic. + attestation_flow_->GetCertificate( + kEnterpriseMachineKey, + base::Bind(DBusStringCallback, + base::Bind(&AttestationPolicyObserver::UploadCertificate, + weak_factory_.GetWeakPtr()), + DBUS_METHOD_CALL_SUCCESS)); +} + +void AttestationPolicyObserver::GetExistingCertificate() { + cryptohome_client_->TpmAttestationGetCertificate( + CryptohomeClient::DEVICE_KEY, + kEnterpriseMachineKey, + base::Bind(DBusStringCallback, + base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, + weak_factory_.GetWeakPtr()))); +} + +void AttestationPolicyObserver::CheckCertificateExpiry( + const std::string& certificate) { + // TODO(dkrahn): Check if the certificate will expire soon, for now assume no. + CheckIfUploaded(certificate); +} + +void AttestationPolicyObserver::UploadCertificate( + const std::string& certificate) { + // TODO(dkrahn): Upload the certificate. +} + +void AttestationPolicyObserver::CheckIfUploaded( + const std::string& certificate) { + // TODO(dkrahn): Check if we've already uploaded the certificate. +} + +} // namespace attestation +} // namespace chromeos diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.h b/chrome/browser/chromeos/attestation/attestation_policy_observer.h new file mode 100644 index 0000000..368ac59 --- /dev/null +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.h @@ -0,0 +1,89 @@ +// Copyright (c) 2013 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_CHROMEOS_ATTESTATION_ATTESTATION_POLICY_OBSERVER_H_ +#define CHROME_BROWSER_CHROMEOS_ATTESTATION_ATTESTATION_POLICY_OBSERVER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/notification_observer.h" + +namespace policy { +class CloudPolicyClient; +} + +namespace chromeos { + +class CrosSettings; +class CryptohomeClient; + +namespace attestation { + +class AttestationFlow; + +// A class which observes policy changes and triggers device attestation work if +// necessary. +class AttestationPolicyObserver : public content::NotificationObserver { + public: + // The observer immediately connects with CrosSettings to listen for policy + // changes. The CloudPolicyClient is used to upload the device certificate to + // the server if one is created in response to policy changes; it must be in + // the registered state. This class does not take ownership of + // |policy_client|. + explicit AttestationPolicyObserver(policy::CloudPolicyClient* policy_client); + + // A constructor which allows custom CryptohomeClient and AttestationFlow + // implementations. Useful for testing. + AttestationPolicyObserver(policy::CloudPolicyClient* policy_client, + CryptohomeClient* cryptohome_client, + AttestationFlow* attestation_flow); + + virtual ~AttestationPolicyObserver(); + + // content::NotificationObserver: + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + private: + static const char kEnterpriseMachineKey[]; + + // Checks attestation policy and starts any necessary work. + void Start(); + + // Gets a new certificate for the Enterprise Machine Key (EMK). + void GetNewCertificate(); + + // Gets the existing EMK certificate and sends it to CheckCertificateExpiry. + void GetExistingCertificate(); + + // Checks if the given certificate is expired and, if so, get a new one. + void CheckCertificateExpiry(const std::string& certificate); + + // Uploads a certificate to the policy server. + void UploadCertificate(const std::string& certificate); + + // Checks if a certificate has already been uploaded and, if not, upload. + void CheckIfUploaded(const std::string& certificate); + + CrosSettings* cros_settings_; + policy::CloudPolicyClient* policy_client_; + CryptohomeClient* cryptohome_client_; + AttestationFlow* attestation_flow_; + scoped_ptr<AttestationFlow> default_attestation_flow_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate the weak pointers before any other members are destroyed. + base::WeakPtrFactory<AttestationPolicyObserver> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(AttestationPolicyObserver); +}; + +} // namespace attestation +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_ATTESTATION_ATTESTATION_POLICY_OBSERVER_H_ diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc new file mode 100644 index 0000000..3ba9c9a --- /dev/null +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc @@ -0,0 +1,118 @@ +// Copyright (c) 2013 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 "base/bind.h" +#include "base/message_loop.h" +#include "base/run_loop.h" +#include "chrome/browser/chromeos/attestation/attestation_policy_observer.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/cros_settings_names.h" +#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" +#include "chrome/browser/policy/cloud/mock_cloud_policy_client.h" +#include "chromeos/attestation/mock_attestation_flow.h" +#include "chromeos/dbus/mock_cryptohome_client.h" +#include "content/public/test/test_browser_thread.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Invoke; +using testing::StrictMock; +using testing::WithArgs; + +namespace chromeos { +namespace attestation { + +namespace { + +void DBusCallbackFalse(const BoolDBusMethodCallback& callback) { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false)); +} + +void DBusCallbackTrue(const BoolDBusMethodCallback& callback) { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true)); +} + +void DBusDataCallback(const CryptohomeClient::DataMethodCallback& callback) { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true, "fake")); +} + +void CertCallbackSuccess(const AttestationFlow::CertificateCallback& callback) { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, true, "fake_cert")); +} + +} // namespace + +class AttestationPolicyObserverTest : public ::testing::Test { + public: + AttestationPolicyObserverTest() + : message_loop_(MessageLoop::TYPE_UI), + ui_thread_(content::BrowserThread::UI, &message_loop_) { + // Remove the real DeviceSettingsProvider and replace it with a stub. + CrosSettings* cros_settings = CrosSettings::Get(); + device_settings_provider_ = + cros_settings->GetProvider(kDeviceAttestationEnabled); + cros_settings->RemoveSettingsProvider(device_settings_provider_); + cros_settings->AddSettingsProvider(&stub_settings_provider_); + cros_settings->SetBoolean(kDeviceAttestationEnabled, true); + policy_client_.SetDMToken("fake_dm_token"); + } + + virtual ~AttestationPolicyObserverTest() { + // Restore the real DeviceSettingsProvider. + CrosSettings* cros_settings = CrosSettings::Get(); + cros_settings->RemoveSettingsProvider(&stub_settings_provider_); + cros_settings->AddSettingsProvider(device_settings_provider_); + } + + protected: + void Run() { + AttestationPolicyObserver observer(&policy_client_, + &cryptohome_client_, + &attestation_flow_); + base::RunLoop().RunUntilIdle(); + } + + MessageLoop message_loop_; + content::TestBrowserThread ui_thread_; + ScopedTestCrosSettings test_cros_settings_; + CrosSettingsProvider* device_settings_provider_; + StubCrosSettingsProvider stub_settings_provider_; + StrictMock<MockCryptohomeClient> cryptohome_client_; + StrictMock<MockAttestationFlow> attestation_flow_; + StrictMock<policy::MockCloudPolicyClient> policy_client_; +}; + +TEST_F(AttestationPolicyObserverTest, FeatureDisabled) { + CrosSettings* cros_settings = CrosSettings::Get(); + cros_settings->SetBoolean(kDeviceAttestationEnabled, false); + Run(); +} + +TEST_F(AttestationPolicyObserverTest, UnregisteredPolicyClient) { + policy_client_.SetDMToken(""); + Run(); +} + +TEST_F(AttestationPolicyObserverTest, NewCertificate) { + EXPECT_CALL(cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _)) + .WillOnce(WithArgs<2>(Invoke(DBusCallbackFalse))); + EXPECT_CALL(attestation_flow_, GetCertificate(_, _)) + .WillOnce(WithArgs<1>(Invoke(CertCallbackSuccess))); + Run(); +} + +TEST_F(AttestationPolicyObserverTest, KeyExists) { + EXPECT_CALL(cryptohome_client_, TpmAttestationDoesKeyExist(_, _, _)) + .WillOnce(WithArgs<2>(Invoke(DBusCallbackTrue))); + EXPECT_CALL(cryptohome_client_, TpmAttestationGetCertificate(_, _, _)) + .WillOnce(WithArgs<2>(Invoke(DBusDataCallback))); + Run(); +} + +} // namespace attestation +} // namespace chromeos diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc index 5fa7bb3..a61c0b6 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "chrome/browser/chromeos/attestation/attestation_policy_observer.h" #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" #include "chrome/browser/chromeos/policy/enrollment_handler_chromeos.h" #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" @@ -162,6 +163,8 @@ void DeviceCloudPolicyManagerChromeOS::EnrollmentCompleted( core()->StartRefreshScheduler(); core()->TrackRefreshDelayPref(local_state_, prefs::kDevicePolicyRefreshRate); + attestation_policy_observer_.reset( + new chromeos::attestation::AttestationPolicyObserver(client())); } else { StartIfManaged(); } @@ -181,6 +184,8 @@ void DeviceCloudPolicyManagerChromeOS::StartIfManaged() { core()->StartRefreshScheduler(); core()->TrackRefreshDelayPref(local_state_, prefs::kDevicePolicyRefreshRate); + attestation_policy_observer_.reset( + new chromeos::attestation::AttestationPolicyObserver(client())); } } diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h index cf5955f..ecfad01 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h +++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h @@ -17,6 +17,12 @@ #include "chrome/browser/policy/cloud/cloud_policy_manager.h" #include "chrome/browser/policy/cloud/cloud_policy_store.h" +namespace chromeos { +namespace attestation { +class AttestationPolicyObserver; +} +} + class PrefService; namespace policy { @@ -94,6 +100,9 @@ class DeviceCloudPolicyManagerChromeOS : public CloudPolicyManager { // Non-null if there is an enrollment operation pending. scoped_ptr<EnrollmentHandlerChromeOS> enrollment_handler_; + scoped_ptr<chromeos::attestation::AttestationPolicyObserver> + attestation_policy_observer_; + DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyManagerChromeOS); }; diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc index 984d9a8..240030a 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc @@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.h" #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chrome/browser/policy/cloud/cloud_policy_client.h" #include "chrome/browser/policy/cloud/mock_device_management_service.h" @@ -74,6 +75,7 @@ class DeviceCloudPolicyManagerChromeOSTest TestingPrefServiceSimple local_state_; MockDeviceManagementService device_management_service_; + chromeos::ScopedTestCrosSettings test_cros_settings_; DeviceCloudPolicyStoreChromeOS* store_; DeviceCloudPolicyManagerChromeOS manager_; diff --git a/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto b/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto index 34b8cfc..862f518 100644 --- a/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto +++ b/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto @@ -279,6 +279,17 @@ message VariationsParameterProto { optional string parameter = 1; } +message AttestationSettingsProto { + // Attestation involves proving that a cryptographic key is protected by a + // legitimate Chrome OS TPM and reporting the operating mode of the platform. + // This setting enables attestation features at a device level. If this is + // enabled a machine key will be generated and certified by the Chrome OS + // CA. If this setting is disabled, the device will not communicate with the + // Chrome OS CA under any circumstances. Even users with attestation settings + // enabled will not be able to use those features on the device. + optional bool attestation_enabled = 1; +} + message ChromeDeviceSettingsProto { optional DevicePolicyRefreshRateProto device_policy_refresh_rate = 1; optional UserWhitelistProto user_whitelist = 2; @@ -305,4 +316,5 @@ message ChromeDeviceSettingsProto { optional StartUpFlagsProto start_up_flags = 23; optional UptimeLimitProto uptime_limit = 24; optional VariationsParameterProto variations_parameter = 25; + optional AttestationSettingsProto attestation_settings = 26; } diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc index e7ddacc..64b592d 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider.cc @@ -49,6 +49,7 @@ const char* kKnownSettings[] = { kAccountsPrefUsers, kAllowRedeemChromeOsRegistrationOffers, kAppPack, + kDeviceAttestationEnabled, kDeviceOwner, kIdleLogoutTimeout, kIdleLogoutWarningDuration, @@ -63,10 +64,10 @@ const char* kKnownSettings[] = { kScreenSaverTimeout, kSettingProxyEverywhere, kSignedDataRoamingEnabled, + kStartUpFlags, kStartUpUrls, kStatsReportingPref, kSystemTimezonePolicy, - kStartUpFlags, kVariationsRestrictParameter, }; @@ -341,6 +342,7 @@ void DeviceSettingsProvider::SetInPolicy() { // The remaining settings don't support Set(), since they are not // intended to be customizable by the user: // kAppPack + // kDeviceAttestationEnabled // kDeviceOwner // kIdleLogoutTimeout // kIdleLogoutWarningDuration @@ -626,6 +628,10 @@ void DeviceSettingsProvider::DecodeGenericPolicies( kVariationsRestrictParameter, policy.variations_parameter().parameter()); } + + new_values_cache->SetBoolean( + kDeviceAttestationEnabled, + policy.attestation_settings().attestation_enabled()); } void DeviceSettingsProvider::UpdateValuesCache( diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 1aef388..1b8d404 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi @@ -125,6 +125,10 @@ 'browser/chromeos/app_mode/kiosk_app_update_service.h', 'browser/chromeos/app_mode/startup_app_launcher.cc', 'browser/chromeos/app_mode/startup_app_launcher.h', + 'browser/chromeos/attestation/attestation_ca_client.cc', + 'browser/chromeos/attestation/attestation_ca_client.h', + 'browser/chromeos/attestation/attestation_policy_observer.cc', + 'browser/chromeos/attestation/attestation_policy_observer.h', 'browser/chromeos/audio/audio_handler.cc', 'browser/chromeos/audio/audio_handler.h', 'browser/chromeos/audio/audio_pref_handler_impl.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 505579c..1e9853f 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -523,6 +523,7 @@ 'browser/chrome_page_zoom_unittest.cc', 'browser/chrome_process_singleton_win_unittest.cc', 'browser/chromeos/accessibility/magnification_manager_unittest.cc', + 'browser/chromeos/attestation/attestation_policy_observer_unittest.cc', 'browser/chromeos/contacts/contact_database_unittest.cc', 'browser/chromeos/contacts/contact_manager_stub.cc', 'browser/chromeos/contacts/contact_manager_stub.h', diff --git a/chromeos/attestation/OWNERS b/chromeos/attestation/OWNERS new file mode 100644 index 0000000..cd1c574 --- /dev/null +++ b/chromeos/attestation/OWNERS @@ -0,0 +1,2 @@ +mnissler@chromium.org +pastarmovj@chromium.org diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc index 1f0db41..f36403a 100644 --- a/chromeos/attestation/attestation_flow.cc +++ b/chromeos/attestation/attestation_flow.cc @@ -44,11 +44,11 @@ const char AttestationFlow::kEnterpriseMachineKey[] = "attest-ent-machine"; AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, CryptohomeClient* cryptohome_client, - ServerProxy* server_proxy) + scoped_ptr<ServerProxy> server_proxy) : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), async_caller_(async_caller), cryptohome_client_(cryptohome_client), - server_proxy_(server_proxy) { + server_proxy_(server_proxy.Pass()) { } AttestationFlow::~AttestationFlow() { diff --git a/chromeos/attestation/attestation_flow.h b/chromeos/attestation/attestation_flow.h index 572be93..76049d7 100644 --- a/chromeos/attestation/attestation_flow.h +++ b/chromeos/attestation/attestation_flow.h @@ -9,6 +9,7 @@ #include "base/basictypes.h" #include "base/callback_forward.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "chromeos/chromeos_export.h" #include "chromeos/dbus/dbus_method_call_status.h" @@ -54,7 +55,7 @@ class CHROMEOS_EXPORT AttestationFlow { AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, CryptohomeClient* cryptohome_client, - ServerProxy* server_proxy); + scoped_ptr<ServerProxy> server_proxy); virtual ~AttestationFlow(); // Asynchronously gets an attestation certificate bound to the given name. @@ -165,7 +166,7 @@ class CHROMEOS_EXPORT AttestationFlow { base::WeakPtrFactory<AttestationFlow> weak_factory_; cryptohome::AsyncMethodCaller* async_caller_; CryptohomeClient* cryptohome_client_; - ServerProxy* server_proxy_; + scoped_ptr<ServerProxy> server_proxy_; DISALLOW_COPY_AND_ASSIGN(AttestationFlow); }; diff --git a/chromeos/attestation/attestation_flow_unittest.cc b/chromeos/attestation/attestation_flow_unittest.cc index 3adc2410..30ea3cc 100644 --- a/chromeos/attestation/attestation_flow_unittest.cc +++ b/chromeos/attestation/attestation_flow_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" +#include "base/memory/scoped_ptr.h" #include "base/run_loop.h" #include "chromeos/attestation/mock_attestation_flow.h" #include "chromeos/cryptohome/mock_async_method_caller.h" @@ -68,9 +69,9 @@ TEST_F(AttestationFlowTest, GetCertificate) { .Times(1) .InSequence(flow_order); - StrictMock<MockServerProxy> proxy; - proxy.DeferToFake(true); - EXPECT_CALL(proxy, SendEnrollRequest( + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); + proxy->DeferToFake(true); + EXPECT_CALL(*proxy, SendEnrollRequest( cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest, _)).Times(1) .InSequence(flow_order); @@ -88,7 +89,7 @@ TEST_F(AttestationFlowTest, GetCertificate) { .Times(1) .InSequence(flow_order); - EXPECT_CALL(proxy, SendCertificateRequest( + EXPECT_CALL(*proxy, SendCertificateRequest( cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest, _)).Times(1) .InSequence(flow_order); @@ -114,7 +115,8 @@ TEST_F(AttestationFlowTest, GetCertificate) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } @@ -130,7 +132,7 @@ TEST_F(AttestationFlowTest, GetCertificate_NoEK) { .WillRepeatedly(Invoke(DBusCallbackFalse)); // We're not expecting any server calls in this case; StrictMock will verify. - StrictMock<MockServerProxy> proxy; + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); StrictMock<MockObserver> observer; EXPECT_CALL(observer, MockCertificateCallback(false, "")) @@ -139,7 +141,8 @@ TEST_F(AttestationFlowTest, GetCertificate_NoEK) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } @@ -154,9 +157,9 @@ TEST_F(AttestationFlowTest, GetCertificate_EKRejected) { EXPECT_CALL(client, TpmAttestationIsEnrolled(_)) .WillRepeatedly(Invoke(DBusCallbackFalse)); - StrictMock<MockServerProxy> proxy; - proxy.DeferToFake(false); - EXPECT_CALL(proxy, SendEnrollRequest( + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); + proxy->DeferToFake(false); + EXPECT_CALL(*proxy, SendEnrollRequest( cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest, _)).Times(1); @@ -167,7 +170,8 @@ TEST_F(AttestationFlowTest, GetCertificate_EKRejected) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } @@ -187,9 +191,9 @@ TEST_F(AttestationFlowTest, GetCertificate_FailEnroll) { EXPECT_CALL(client, TpmAttestationIsEnrolled(_)) .WillRepeatedly(Invoke(DBusCallbackFalse)); - StrictMock<MockServerProxy> proxy; - proxy.DeferToFake(true); - EXPECT_CALL(proxy, SendEnrollRequest( + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); + proxy->DeferToFake(true); + EXPECT_CALL(*proxy, SendEnrollRequest( cryptohome::MockAsyncMethodCaller::kFakeAttestationEnrollRequest, _)).Times(1); @@ -199,7 +203,8 @@ TEST_F(AttestationFlowTest, GetCertificate_FailEnroll) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } @@ -225,9 +230,9 @@ TEST_F(AttestationFlowTest, GetOwnerCertificateAlreadyEnrolled) { EXPECT_CALL(client, TpmAttestationIsEnrolled(_)) .WillRepeatedly(Invoke(DBusCallbackTrue)); - StrictMock<MockServerProxy> proxy; - proxy.DeferToFake(true); - EXPECT_CALL(proxy, SendCertificateRequest( + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); + proxy->DeferToFake(true); + EXPECT_CALL(*proxy, SendCertificateRequest( cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest, _)).Times(1); @@ -239,7 +244,8 @@ TEST_F(AttestationFlowTest, GetOwnerCertificateAlreadyEnrolled) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("attest-ent-machine", mock_callback); Run(); } @@ -257,7 +263,7 @@ TEST_F(AttestationFlowTest, GetCertificate_FailCreateCertRequest) { .WillRepeatedly(Invoke(DBusCallbackTrue)); // We're not expecting any server calls in this case; StrictMock will verify. - StrictMock<MockServerProxy> proxy; + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); StrictMock<MockObserver> observer; EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); @@ -265,7 +271,8 @@ TEST_F(AttestationFlowTest, GetCertificate_FailCreateCertRequest) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } @@ -282,9 +289,9 @@ TEST_F(AttestationFlowTest, GetCertificate_CertRequestRejected) { EXPECT_CALL(client, TpmAttestationIsEnrolled(_)) .WillRepeatedly(Invoke(DBusCallbackTrue)); - StrictMock<MockServerProxy> proxy; - proxy.DeferToFake(false); - EXPECT_CALL(proxy, SendCertificateRequest( + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); + proxy->DeferToFake(false); + EXPECT_CALL(*proxy, SendCertificateRequest( cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest, _)).Times(1); @@ -294,7 +301,8 @@ TEST_F(AttestationFlowTest, GetCertificate_CertRequestRejected) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } @@ -308,7 +316,7 @@ TEST_F(AttestationFlowTest, GetCertificate_FailIsEnrolled) { .WillRepeatedly(Invoke(DBusCallbackFail)); // We're not expecting any server calls in this case; StrictMock will verify. - StrictMock<MockServerProxy> proxy; + scoped_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); StrictMock<MockObserver> observer; EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); @@ -316,7 +324,8 @@ TEST_F(AttestationFlowTest, GetCertificate_FailIsEnrolled) { &MockObserver::MockCertificateCallback, base::Unretained(&observer)); - AttestationFlow flow(&async_caller, &client, &proxy); + scoped_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, proxy_interface.Pass()); flow.GetCertificate("test", mock_callback); Run(); } diff --git a/chromeos/attestation/mock_attestation_flow.cc b/chromeos/attestation/mock_attestation_flow.cc index 71de13e..b776899 100644 --- a/chromeos/attestation/mock_attestation_flow.cc +++ b/chromeos/attestation/mock_attestation_flow.cc @@ -4,6 +4,7 @@ #include "chromeos/attestation/mock_attestation_flow.h" +#include "base/memory/scoped_ptr.h" #include "testing/gmock/include/gmock/gmock.h" using testing::_; @@ -42,5 +43,10 @@ MockObserver::MockObserver() {} MockObserver::~MockObserver() {} +MockAttestationFlow::MockAttestationFlow() + : AttestationFlow(NULL, NULL, scoped_ptr<ServerProxy>()) {} + +MockAttestationFlow::~MockAttestationFlow() {} + } // namespace attestation } // namespace chromeos diff --git a/chromeos/attestation/mock_attestation_flow.h b/chromeos/attestation/mock_attestation_flow.h index c9dc9d5..59462c54 100644 --- a/chromeos/attestation/mock_attestation_flow.h +++ b/chromeos/attestation/mock_attestation_flow.h @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef CHROMEOS_ATTESTATION_MOCK_ATTESTATION_FLOW_H_ +#define CHROMEOS_ATTESTATION_MOCK_ATTESTATION_FLOW_H_ + #include "chromeos/attestation/attestation_flow.h" #include "base/basictypes.h" @@ -57,5 +60,16 @@ class MockObserver { MOCK_METHOD2(MockCertificateCallback, void(bool, const std::string&)); }; +class MockAttestationFlow : public AttestationFlow { + public: + MockAttestationFlow(); + virtual ~MockAttestationFlow(); + + MOCK_METHOD2(GetCertificate, void(const std::string&, + const CertificateCallback&)); +}; + } // namespace attestation } // namespace chromeos + +#endif // CHROMEOS_ATTESTATION_MOCK_ATTESTATION_FLOW_H_ |