Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / chromeos / attestation / platform_verification_flow_unittest.cc
bloba3101e54bfece9f4e0bb4ffa328f7bbd7797c91a
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.
5 #include <string>
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/chromeos/attestation/attestation_signed_data.pb.h"
11 #include "chrome/browser/chromeos/attestation/fake_certificate.h"
12 #include "chrome/browser/chromeos/attestation/platform_verification_flow.h"
13 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
14 #include "chrome/browser/chromeos/settings/cros_settings.h"
15 #include "chrome/browser/chromeos/settings/device_settings_service.h"
16 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
17 #include "chrome/browser/profiles/profile_impl.h"
18 #include "chrome/common/pref_names.h"
19 #include "chromeos/attestation/mock_attestation_flow.h"
20 #include "chromeos/cryptohome/mock_async_method_caller.h"
21 #include "chromeos/dbus/fake_cryptohome_client.h"
22 #include "chromeos/settings/cros_settings_names.h"
23 #include "content/public/test/test_browser_thread.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using testing::_;
27 using testing::DoAll;
28 using testing::Invoke;
29 using testing::Return;
30 using testing::SetArgumentPointee;
31 using testing::StrictMock;
32 using testing::WithArgs;
34 namespace chromeos {
35 namespace attestation {
37 namespace {
39 const char kTestID[] = "test_id";
40 const char kTestChallenge[] = "test_challenge";
41 const char kTestSignedData[] = "test_challenge_with_salt";
42 const char kTestSignature[] = "test_signature";
43 const char kTestCertificate[] = "test_certificate";
44 const char kTestEmail[] = "test_email@chromium.org";
45 const char kTestURL[] = "http://mytestdomain/test";
47 class FakeDelegate : public PlatformVerificationFlow::Delegate {
48 public:
49 FakeDelegate()
50 : url_(kTestURL),
51 is_permitted_by_user_(true),
52 is_in_supported_mode_(true) {
53 // Configure a user for the mock user manager.
54 mock_user_manager_.SetActiveUser(kTestEmail);
56 ~FakeDelegate() override {}
58 const GURL& GetURL(content::WebContents* web_contents) override {
59 return url_;
62 user_manager::User* GetUser(content::WebContents* web_contents) override {
63 return mock_user_manager_.GetActiveUser();
66 bool IsPermittedByUser(content::WebContents* web_contents) override {
67 return is_permitted_by_user_;
70 bool IsInSupportedMode(content::WebContents* web_contents) override {
71 return is_in_supported_mode_;
74 void set_url(const GURL& url) {
75 url_ = url;
78 void set_is_permitted_by_user(bool is_permitted_by_user) {
79 is_permitted_by_user_ = is_permitted_by_user;
82 void set_is_in_supported_mode(bool is_in_supported_mode) {
83 is_in_supported_mode_ = is_in_supported_mode;
86 private:
87 MockUserManager mock_user_manager_;
88 GURL url_;
89 bool is_permitted_by_user_;
90 bool is_in_supported_mode_;
92 DISALLOW_COPY_AND_ASSIGN(FakeDelegate);
95 class CustomFakeCryptohomeClient : public FakeCryptohomeClient {
96 public:
97 CustomFakeCryptohomeClient() : call_status_(DBUS_METHOD_CALL_SUCCESS),
98 attestation_enrolled_(true),
99 attestation_prepared_(true) {}
100 void TpmAttestationIsEnrolled(
101 const BoolDBusMethodCallback& callback) override {
102 base::MessageLoop::current()->PostTask(FROM_HERE,
103 base::Bind(callback,
104 call_status_,
105 attestation_enrolled_));
108 void TpmAttestationIsPrepared(
109 const BoolDBusMethodCallback& callback) override {
110 base::MessageLoop::current()->PostTask(FROM_HERE,
111 base::Bind(callback,
112 call_status_,
113 attestation_prepared_));
116 void set_call_status(DBusMethodCallStatus call_status) {
117 call_status_ = call_status;
120 void set_attestation_enrolled(bool attestation_enrolled) {
121 attestation_enrolled_ = attestation_enrolled;
124 void set_attestation_prepared(bool attestation_prepared) {
125 attestation_prepared_ = attestation_prepared;
128 private:
129 DBusMethodCallStatus call_status_;
130 bool attestation_enrolled_;
131 bool attestation_prepared_;
134 } // namespace
136 class PlatformVerificationFlowTest : public ::testing::Test {
137 public:
138 PlatformVerificationFlowTest()
139 : ui_thread_(content::BrowserThread::UI, &message_loop_),
140 certificate_success_(true),
141 fake_certificate_index_(0),
142 sign_challenge_success_(true),
143 result_(PlatformVerificationFlow::INTERNAL_ERROR) {}
145 void SetUp() {
146 // Create a verifier for tests to call.
147 verifier_ = new PlatformVerificationFlow(&mock_attestation_flow_,
148 &mock_async_caller_,
149 &fake_cryptohome_client_,
150 &fake_delegate_);
152 // Create callbacks for tests to use with verifier_.
153 callback_ = base::Bind(&PlatformVerificationFlowTest::FakeChallengeCallback,
154 base::Unretained(this));
156 // Configure the global cros_settings.
157 CrosSettings* cros_settings = CrosSettings::Get();
158 device_settings_provider_ =
159 cros_settings->GetProvider(kAttestationForContentProtectionEnabled);
160 cros_settings->RemoveSettingsProvider(device_settings_provider_);
161 cros_settings->AddSettingsProvider(&stub_settings_provider_);
162 cros_settings->SetBoolean(kAttestationForContentProtectionEnabled, true);
165 void TearDown() {
166 // Restore the real DeviceSettingsProvider.
167 CrosSettings* cros_settings = CrosSettings::Get();
168 cros_settings->RemoveSettingsProvider(&stub_settings_provider_);
169 cros_settings->AddSettingsProvider(device_settings_provider_);
172 void ExpectAttestationFlow() {
173 // When consent is not given or the feature is disabled, it is important
174 // that there are no calls to the attestation service. Thus, a test must
175 // explicitly expect these calls or the mocks will fail the test.
177 // Configure the mock AttestationFlow to call FakeGetCertificate.
178 EXPECT_CALL(mock_attestation_flow_,
179 GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE,
180 kTestEmail, kTestID, _, _))
181 .WillRepeatedly(WithArgs<4>(Invoke(
182 this, &PlatformVerificationFlowTest::FakeGetCertificate)));
184 // Configure the mock AsyncMethodCaller to call FakeSignChallenge.
185 std::string expected_key_name = std::string(kContentProtectionKeyPrefix) +
186 std::string(kTestID);
187 EXPECT_CALL(mock_async_caller_,
188 TpmAttestationSignSimpleChallenge(KEY_USER, kTestEmail,
189 expected_key_name,
190 kTestChallenge, _))
191 .WillRepeatedly(WithArgs<4>(Invoke(
192 this, &PlatformVerificationFlowTest::FakeSignChallenge)));
195 void FakeGetCertificate(
196 const AttestationFlow::CertificateCallback& callback) {
197 std::string certificate =
198 (fake_certificate_index_ < fake_certificate_list_.size()) ?
199 fake_certificate_list_[fake_certificate_index_] : kTestCertificate;
200 base::MessageLoop::current()->PostTask(FROM_HERE,
201 base::Bind(callback,
202 certificate_success_,
203 certificate));
204 ++fake_certificate_index_;
207 void FakeSignChallenge(
208 const cryptohome::AsyncMethodCaller::DataCallback& callback) {
209 base::MessageLoop::current()->PostTask(
210 FROM_HERE,
211 base::Bind(callback,
212 sign_challenge_success_,
213 CreateFakeResponseProto()));
216 void FakeChallengeCallback(PlatformVerificationFlow::Result result,
217 const std::string& salt,
218 const std::string& signature,
219 const std::string& certificate) {
220 result_ = result;
221 challenge_salt_ = salt;
222 challenge_signature_ = signature;
223 certificate_ = certificate;
226 std::string CreateFakeResponseProto() {
227 SignedData pb;
228 pb.set_data(kTestSignedData);
229 pb.set_signature(kTestSignature);
230 std::string serial;
231 CHECK(pb.SerializeToString(&serial));
232 return serial;
235 protected:
236 base::MessageLoopForUI message_loop_;
237 content::TestBrowserThread ui_thread_;
238 StrictMock<MockAttestationFlow> mock_attestation_flow_;
239 cryptohome::MockAsyncMethodCaller mock_async_caller_;
240 CustomFakeCryptohomeClient fake_cryptohome_client_;
241 FakeDelegate fake_delegate_;
242 CrosSettingsProvider* device_settings_provider_;
243 StubCrosSettingsProvider stub_settings_provider_;
244 ScopedTestDeviceSettingsService test_device_settings_service_;
245 ScopedTestCrosSettings test_cros_settings_;
246 scoped_refptr<PlatformVerificationFlow> verifier_;
248 // Controls result of FakeGetCertificate.
249 bool certificate_success_;
250 std::vector<std::string> fake_certificate_list_;
251 size_t fake_certificate_index_;
253 // Controls result of FakeSignChallenge.
254 bool sign_challenge_success_;
256 // Callback functions and data.
257 PlatformVerificationFlow::ChallengeCallback callback_;
258 PlatformVerificationFlow::Result result_;
259 std::string challenge_salt_;
260 std::string challenge_signature_;
261 std::string certificate_;
264 TEST_F(PlatformVerificationFlowTest, Success) {
265 ExpectAttestationFlow();
266 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
267 base::RunLoop().RunUntilIdle();
268 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_);
269 EXPECT_EQ(kTestSignedData, challenge_salt_);
270 EXPECT_EQ(kTestSignature, challenge_signature_);
271 EXPECT_EQ(kTestCertificate, certificate_);
274 TEST_F(PlatformVerificationFlowTest, NotPermittedByUser) {
275 fake_delegate_.set_is_permitted_by_user(false);
276 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
277 base::RunLoop().RunUntilIdle();
278 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_);
281 TEST_F(PlatformVerificationFlowTest, FeatureDisabledByPolicy) {
282 CrosSettings::Get()->SetBoolean(kAttestationForContentProtectionEnabled,
283 false);
284 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
285 base::RunLoop().RunUntilIdle();
286 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_);
289 TEST_F(PlatformVerificationFlowTest, NotVerified) {
290 certificate_success_ = false;
291 ExpectAttestationFlow();
292 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
293 base::RunLoop().RunUntilIdle();
294 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_);
297 TEST_F(PlatformVerificationFlowTest, ChallengeSigningError) {
298 sign_challenge_success_ = false;
299 ExpectAttestationFlow();
300 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
301 base::RunLoop().RunUntilIdle();
302 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_);
305 TEST_F(PlatformVerificationFlowTest, DBusFailure) {
306 fake_cryptohome_client_.set_call_status(DBUS_METHOD_CALL_FAILURE);
307 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
308 base::RunLoop().RunUntilIdle();
309 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_);
312 TEST_F(PlatformVerificationFlowTest, Timeout) {
313 verifier_->set_timeout_delay(base::TimeDelta::FromSeconds(0));
314 ExpectAttestationFlow();
315 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
316 base::RunLoop().RunUntilIdle();
317 EXPECT_EQ(PlatformVerificationFlow::TIMEOUT, result_);
320 TEST_F(PlatformVerificationFlowTest, ExpiredCert) {
321 ExpectAttestationFlow();
322 fake_certificate_list_.resize(2);
323 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(-1),
324 &fake_certificate_list_[0]));
325 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(1),
326 &fake_certificate_list_[1]));
327 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
328 base::RunLoop().RunUntilIdle();
329 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_);
330 EXPECT_EQ(certificate_, fake_certificate_list_[1]);
333 TEST_F(PlatformVerificationFlowTest, UnsupportedMode) {
334 fake_delegate_.set_is_in_supported_mode(false);
335 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
336 base::RunLoop().RunUntilIdle();
337 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_);
340 TEST_F(PlatformVerificationFlowTest, AttestationNotPrepared) {
341 fake_cryptohome_client_.set_attestation_enrolled(false);
342 fake_cryptohome_client_.set_attestation_prepared(false);
343 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_);
344 base::RunLoop().RunUntilIdle();
345 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_);
348 } // namespace attestation
349 } // namespace chromeos