summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkrahn@google.com <dkrahn@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-19 20:34:35 +0000
committerdkrahn@google.com <dkrahn@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-19 20:34:35 +0000
commiteda0a0b16697dab1fc2d45d6cfe38652044b88d5 (patch)
treef8448fcc9809fd7a001947a3b146c1b32a2eeb32
parent450944caa9b0aaf7639a74ffc18b1afe057a873c (diff)
downloadchromium_src-eda0a0b16697dab1fc2d45d6cfe38652044b88d5.zip
chromium_src-eda0a0b16697dab1fc2d45d6cfe38652044b88d5.tar.gz
chromium_src-eda0a0b16697dab1fc2d45d6cfe38652044b88d5.tar.bz2
Created AttestationPolicyObserver.
AttestationPolicyObserver performs Chrome OS attestation work in response to policy changes. This CL integrates AttestationPolicyObserver with the Chrome OS device policy infrastructure. It also defines a AttestationCAClient skeleton which is necessary to instantiate AttestationFlow and changes AttestationFlow to take ownership of its ServerProxy instance. BUG=chromium:219959 TEST=unit_tests; chromeos_unittests Review URL: https://chromiumcodereview.appspot.com/12556004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195266 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--WATCHLISTS5
-rw-r--r--chrome/browser/chromeos/attestation/OWNERS2
-rw-r--r--chrome/browser/chromeos/attestation/attestation_ca_client.cc31
-rw-r--r--chrome/browser/chromeos/attestation/attestation_ca_client.h37
-rw-r--r--chrome/browser/chromeos/attestation/attestation_policy_observer.cc187
-rw-r--r--chrome/browser/chromeos/attestation/attestation_policy_observer.h89
-rw-r--r--chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc118
-rw-r--r--chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc5
-rw-r--r--chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h9
-rw-r--r--chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc2
-rw-r--r--chrome/browser/chromeos/policy/proto/chrome_device_policy.proto12
-rw-r--r--chrome/browser/chromeos/settings/device_settings_provider.cc8
-rw-r--r--chrome/chrome_browser_chromeos.gypi4
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chromeos/attestation/OWNERS2
-rw-r--r--chromeos/attestation/attestation_flow.cc4
-rw-r--r--chromeos/attestation/attestation_flow.h5
-rw-r--r--chromeos/attestation/attestation_flow_unittest.cc63
-rw-r--r--chromeos/attestation/mock_attestation_flow.cc6
-rw-r--r--chromeos/attestation/mock_attestation_flow.h14
20 files changed, 572 insertions, 32 deletions
diff --git a/WATCHLISTS b/WATCHLISTS
index ce6cbe0..4d43eb9 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -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_