1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/bind.h"
6#include "base/memory/ref_counted.h"
7#include "base/run_loop.h"
8#include "base/threading/platform_thread.h"
9#include "base/time/time.h"
10#include "chrome/browser/chromeos/attestation/platform_verification_flow.h"
11#include "chrome/browser/chromeos/policy/device_policy_builder.h"
12#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
13#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
14#include "chrome/browser/chromeos/settings/device_settings_service.h"
15#include "chrome/browser/ui/browser.h"
16#include "chrome/browser/ui/tabs/tab_strip_model.h"
17#include "chromeos/dbus/fake_cryptohome_client.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using chromeos::attestation::PlatformVerificationFlow;
21
22namespace policy {
23
24class CustomFakeCryptohomeClient : public chromeos::FakeCryptohomeClient {
25 public:
26  virtual void TpmAttestationIsEnrolled(
27      const chromeos::BoolDBusMethodCallback& callback) OVERRIDE {
28    base::MessageLoop::current()->PostTask(
29        FROM_HERE,
30        base::Bind(callback, chromeos::DBUS_METHOD_CALL_FAILURE, false));
31  }
32};
33
34class AttestationDevicePolicyTest
35    : public DevicePolicyCrosBrowserTest,
36      public chromeos::DeviceSettingsService::Observer {
37 public:
38    // DeviceSettingsService::Observer
39    virtual void OwnershipStatusChanged() OVERRIDE {}
40    virtual void DeviceSettingsUpdated() OVERRIDE {
41      operation_complete_ = true;
42    }
43
44 protected:
45  AttestationDevicePolicyTest() : operation_complete_(false) {}
46
47  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
48    DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
49    InstallOwnerKey();
50    RefreshDevicePolicy();
51  }
52
53  // Refreshes device policy and waits for it to be applied.
54  virtual void SyncRefreshDevicePolicy() {
55    chromeos::DeviceSettingsService::Get()->AddObserver(this);
56    RefreshDevicePolicy();
57    WaitForAsyncOperation();
58    chromeos::DeviceSettingsService::Get()->RemoveObserver(this);
59  }
60
61  enterprise_management::AttestationSettingsProto* GetDevicePolicyProto() {
62    return device_policy()->payload().mutable_attestation_settings();
63  }
64
65  // A callback for PlatformVerificationFlow::ChallengePlatformKey.
66  void Callback(PlatformVerificationFlow::Result result,
67                const std::string& signed_data,
68                const std::string& signature,
69                const std::string& platform_key_certificate) {
70    result_ = result;
71    operation_complete_ = true;
72  }
73
74  // Synchronously do what the content protection code path does when it wants
75  // to verify a Chrome OS platform.
76  PlatformVerificationFlow::Result SyncContentProtectionAttestation() {
77    scoped_refptr<PlatformVerificationFlow> verifier(
78        new PlatformVerificationFlow(NULL, NULL, &fake_cryptohome_client_,
79                                     NULL));
80    verifier->ChallengePlatformKey(
81      browser()->tab_strip_model()->GetActiveWebContents(),
82      "fake_service_id",
83      "fake_challenge",
84      base::Bind(&AttestationDevicePolicyTest::Callback, this));
85    WaitForAsyncOperation();
86    return result_;
87  }
88
89 private:
90  bool operation_complete_;
91  PlatformVerificationFlow::Result result_;
92  CustomFakeCryptohomeClient fake_cryptohome_client_;
93
94  void WaitForAsyncOperation() {
95    while (!operation_complete_) {
96      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
97      base::RunLoop pump;
98      pump.RunUntilIdle();
99    }
100    // Reset for the next call.
101    operation_complete_ = false;
102  }
103
104  DISALLOW_COPY_AND_ASSIGN(AttestationDevicePolicyTest);
105};
106
107IN_PROC_BROWSER_TEST_F(AttestationDevicePolicyTest, ContentProtectionTest) {
108  EXPECT_NE(PlatformVerificationFlow::POLICY_REJECTED,
109            SyncContentProtectionAttestation());
110
111  GetDevicePolicyProto()->set_content_protection_enabled(false);
112  SyncRefreshDevicePolicy();
113
114  EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED,
115            SyncContentProtectionAttestation());
116
117  GetDevicePolicyProto()->set_content_protection_enabled(true);
118  SyncRefreshDevicePolicy();
119
120  EXPECT_NE(PlatformVerificationFlow::POLICY_REJECTED,
121            SyncContentProtectionAttestation());
122}
123
124} // namespace policy
125