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.
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/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/content_settings/host_content_settings_map.h"
18 #include "chrome/browser/profiles/profile_impl.h"
19 #include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
20 #include "chrome/common/content_settings_pattern.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/base/testing_pref_service_syncable.h"
23 #include "chromeos/attestation/mock_attestation_flow.h"
24 #include "chromeos/cryptohome/mock_async_method_caller.h"
25 #include "chromeos/dbus/fake_cryptohome_client.h"
26 #include "chromeos/settings/cros_settings_names.h"
27 #include "content/public/test/test_browser_thread.h"
28 #include "testing/gtest/include/gtest/gtest.h"
32 using testing::Invoke
;
33 using testing::Return
;
34 using testing::SetArgumentPointee
;
35 using testing::StrictMock
;
36 using testing::WithArgs
;
39 namespace attestation
{
43 const char kTestID
[] = "test_id";
44 const char kTestChallenge
[] = "test_challenge";
45 const char kTestSignedData
[] = "test_challenge_with_salt";
46 const char kTestSignature
[] = "test_signature";
47 const char kTestCertificate
[] = "test_certificate";
48 const char kTestEmail
[] = "test_email@chromium.org";
49 const char kTestURL
[] = "http://mytestdomain/test";
50 const char kTestURLSecure
[] = "https://mytestdomain/test";
51 const char kTestURLExtension
[] = "chrome-extension://mytestextension";
53 class FakeDelegate
: public PlatformVerificationFlow::Delegate
{
55 FakeDelegate() : response_(PlatformVerificationFlow::CONSENT_RESPONSE_ALLOW
),
56 num_consent_calls_(0),
58 is_incognito_(false) {
59 // Configure a user for the mock user manager.
60 mock_user_manager_
.SetActiveUser(kTestEmail
);
62 virtual ~FakeDelegate() {}
65 ProfileImpl::RegisterProfilePrefs(pref_service_
.registry());
66 chrome::DeviceIDFetcher::RegisterProfilePrefs(pref_service_
.registry());
67 PlatformVerificationFlow::RegisterProfilePrefs(pref_service_
.registry());
68 HostContentSettingsMap::RegisterProfilePrefs(pref_service_
.registry());
69 content_settings_
= new HostContentSettingsMap(&pref_service_
, false);
73 content_settings_
->ShutdownOnUIThread();
76 virtual void ShowConsentPrompt(
77 content::WebContents
* web_contents
,
78 const PlatformVerificationFlow::Delegate::ConsentCallback
& callback
)
81 callback
.Run(response_
);
84 virtual PrefService
* GetPrefs(content::WebContents
* web_contents
) OVERRIDE
{
85 return &pref_service_
;
88 virtual const GURL
& GetURL(content::WebContents
* web_contents
) OVERRIDE
{
92 virtual User
* GetUser(content::WebContents
* web_contents
) OVERRIDE
{
93 return mock_user_manager_
.GetActiveUser();
96 virtual HostContentSettingsMap
* GetContentSettings(
97 content::WebContents
* web_contents
) OVERRIDE
{
98 return content_settings_
;
101 virtual bool IsGuestOrIncognito(content::WebContents
* web_contents
) OVERRIDE
{
102 return is_incognito_
;
105 void set_response(PlatformVerificationFlow::ConsentResponse response
) {
106 response_
= response
;
109 int num_consent_calls() {
110 return num_consent_calls_
;
113 TestingPrefServiceSyncable
& pref_service() {
114 return pref_service_
;
117 void set_url(const GURL
& url
) {
121 void set_is_incognito(bool is_incognito
) {
122 is_incognito_
= is_incognito
;
126 PlatformVerificationFlow::ConsentResponse response_
;
127 int num_consent_calls_
;
128 TestingPrefServiceSyncable pref_service_
;
129 MockUserManager mock_user_manager_
;
131 scoped_refptr
<HostContentSettingsMap
> content_settings_
;
134 DISALLOW_COPY_AND_ASSIGN(FakeDelegate
);
137 class CustomFakeCryptohomeClient
: public FakeCryptohomeClient
{
139 CustomFakeCryptohomeClient() : call_status_(DBUS_METHOD_CALL_SUCCESS
),
140 attestation_enrolled_(true),
141 attestation_prepared_(true) {}
142 virtual void TpmAttestationIsEnrolled(
143 const BoolDBusMethodCallback
& callback
) OVERRIDE
{
144 base::MessageLoop::current()->PostTask(FROM_HERE
,
147 attestation_enrolled_
));
150 virtual void TpmAttestationIsPrepared(
151 const BoolDBusMethodCallback
& callback
) OVERRIDE
{
152 base::MessageLoop::current()->PostTask(FROM_HERE
,
155 attestation_prepared_
));
158 void set_call_status(DBusMethodCallStatus call_status
) {
159 call_status_
= call_status
;
162 void set_attestation_enrolled(bool attestation_enrolled
) {
163 attestation_enrolled_
= attestation_enrolled
;
166 void set_attestation_prepared(bool attestation_prepared
) {
167 attestation_prepared_
= attestation_prepared
;
171 DBusMethodCallStatus call_status_
;
172 bool attestation_enrolled_
;
173 bool attestation_prepared_
;
178 class PlatformVerificationFlowTest
: public ::testing::Test
{
180 PlatformVerificationFlowTest()
181 : ui_thread_(content::BrowserThread::UI
, &message_loop_
),
182 certificate_success_(true),
183 fake_certificate_index_(0),
184 sign_challenge_success_(true),
185 result_(PlatformVerificationFlow::INTERNAL_ERROR
) {}
188 fake_delegate_
.SetUp();
190 // Create a verifier for tests to call.
191 verifier_
= new PlatformVerificationFlow(&mock_attestation_flow_
,
193 &fake_cryptohome_client_
,
196 // Create callbacks for tests to use with verifier_.
197 callback_
= base::Bind(&PlatformVerificationFlowTest::FakeChallengeCallback
,
198 base::Unretained(this));
200 // Configure the global cros_settings.
201 CrosSettings
* cros_settings
= CrosSettings::Get();
202 device_settings_provider_
=
203 cros_settings
->GetProvider(kAttestationForContentProtectionEnabled
);
204 cros_settings
->RemoveSettingsProvider(device_settings_provider_
);
205 cros_settings
->AddSettingsProvider(&stub_settings_provider_
);
206 cros_settings
->SetBoolean(kAttestationForContentProtectionEnabled
, true);
208 // Start with the first-time setting set since most tests want this.
209 fake_delegate_
.pref_service().SetUserPref(prefs::kRAConsentFirstTime
,
210 new base::FundamentalValue(true));
215 // Restore the real DeviceSettingsProvider.
216 CrosSettings
* cros_settings
= CrosSettings::Get();
217 cros_settings
->RemoveSettingsProvider(&stub_settings_provider_
);
218 cros_settings
->AddSettingsProvider(device_settings_provider_
);
219 fake_delegate_
.TearDown();
222 void ExpectAttestationFlow() {
223 // When consent is not given or the feature is disabled, it is important
224 // that there are no calls to the attestation service. Thus, a test must
225 // explicitly expect these calls or the mocks will fail the test.
227 // Configure the mock AttestationFlow to call FakeGetCertificate.
228 EXPECT_CALL(mock_attestation_flow_
,
229 GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE
,
230 kTestEmail
, kTestID
, _
, _
))
231 .WillRepeatedly(WithArgs
<4>(Invoke(
232 this, &PlatformVerificationFlowTest::FakeGetCertificate
)));
234 // Configure the mock AsyncMethodCaller to call FakeSignChallenge.
235 std::string expected_key_name
= std::string(kContentProtectionKeyPrefix
) +
236 std::string(kTestID
);
237 EXPECT_CALL(mock_async_caller_
,
238 TpmAttestationSignSimpleChallenge(KEY_USER
, kTestEmail
,
241 .WillRepeatedly(WithArgs
<4>(Invoke(
242 this, &PlatformVerificationFlowTest::FakeSignChallenge
)));
245 void SetUserConsent(const GURL
& url
, bool allow
) {
246 verifier_
->RecordDomainConsent(fake_delegate_
.GetContentSettings(NULL
),
251 void FakeGetCertificate(
252 const AttestationFlow::CertificateCallback
& callback
) {
253 std::string certificate
=
254 (fake_certificate_index_
< fake_certificate_list_
.size()) ?
255 fake_certificate_list_
[fake_certificate_index_
] : kTestCertificate
;
256 base::MessageLoop::current()->PostTask(FROM_HERE
,
258 certificate_success_
,
260 ++fake_certificate_index_
;
263 void FakeSignChallenge(
264 const cryptohome::AsyncMethodCaller::DataCallback
& callback
) {
265 base::MessageLoop::current()->PostTask(
268 sign_challenge_success_
,
269 CreateFakeResponseProto()));
272 void FakeChallengeCallback(PlatformVerificationFlow::Result result
,
273 const std::string
& salt
,
274 const std::string
& signature
,
275 const std::string
& certificate
) {
277 challenge_salt_
= salt
;
278 challenge_signature_
= signature
;
279 certificate_
= certificate
;
282 std::string
CreateFakeResponseProto() {
284 pb
.set_data(kTestSignedData
);
285 pb
.set_signature(kTestSignature
);
287 CHECK(pb
.SerializeToString(&serial
));
292 base::MessageLoopForUI message_loop_
;
293 content::TestBrowserThread ui_thread_
;
294 StrictMock
<MockAttestationFlow
> mock_attestation_flow_
;
295 cryptohome::MockAsyncMethodCaller mock_async_caller_
;
296 CustomFakeCryptohomeClient fake_cryptohome_client_
;
297 FakeDelegate fake_delegate_
;
298 CrosSettingsProvider
* device_settings_provider_
;
299 StubCrosSettingsProvider stub_settings_provider_
;
300 ScopedTestDeviceSettingsService test_device_settings_service_
;
301 ScopedTestCrosSettings test_cros_settings_
;
302 scoped_refptr
<PlatformVerificationFlow
> verifier_
;
304 // Controls result of FakeGetCertificate.
305 bool certificate_success_
;
306 std::vector
<std::string
> fake_certificate_list_
;
307 size_t fake_certificate_index_
;
309 // Controls result of FakeSignChallenge.
310 bool sign_challenge_success_
;
312 // Callback functions and data.
313 PlatformVerificationFlow::ChallengeCallback callback_
;
314 PlatformVerificationFlow::Result result_
;
315 std::string challenge_salt_
;
316 std::string challenge_signature_
;
317 std::string certificate_
;
320 TEST_F(PlatformVerificationFlowTest
, SuccessNoConsent
) {
321 SetUserConsent(GURL(kTestURL
), true);
322 // Make sure the call will fail if consent is requested.
323 fake_delegate_
.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY
);
324 ExpectAttestationFlow();
325 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
326 base::RunLoop().RunUntilIdle();
327 EXPECT_EQ(PlatformVerificationFlow::SUCCESS
, result_
);
328 EXPECT_EQ(kTestSignedData
, challenge_salt_
);
329 EXPECT_EQ(kTestSignature
, challenge_signature_
);
330 EXPECT_EQ(kTestCertificate
, certificate_
);
331 EXPECT_EQ(0, fake_delegate_
.num_consent_calls());
334 TEST_F(PlatformVerificationFlowTest
, SuccessWithAttestationConsent
) {
335 SetUserConsent(GURL(kTestURL
), true);
336 fake_cryptohome_client_
.set_attestation_enrolled(false);
337 ExpectAttestationFlow();
338 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
339 base::RunLoop().RunUntilIdle();
340 EXPECT_EQ(PlatformVerificationFlow::SUCCESS
, result_
);
341 EXPECT_EQ(kTestSignedData
, challenge_salt_
);
342 EXPECT_EQ(kTestSignature
, challenge_signature_
);
343 EXPECT_EQ(kTestCertificate
, certificate_
);
344 EXPECT_EQ(1, fake_delegate_
.num_consent_calls());
347 TEST_F(PlatformVerificationFlowTest
, SuccessWithFirstTimeConsent
) {
348 SetUserConsent(GURL(kTestURL
), true);
349 fake_delegate_
.pref_service().SetUserPref(prefs::kRAConsentFirstTime
,
350 new base::FundamentalValue(false));
351 ExpectAttestationFlow();
352 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
353 base::RunLoop().RunUntilIdle();
354 EXPECT_EQ(PlatformVerificationFlow::SUCCESS
, result_
);
355 EXPECT_EQ(kTestSignedData
, challenge_salt_
);
356 EXPECT_EQ(kTestSignature
, challenge_signature_
);
357 EXPECT_EQ(kTestCertificate
, certificate_
);
358 EXPECT_EQ(1, fake_delegate_
.num_consent_calls());
361 TEST_F(PlatformVerificationFlowTest
, ConsentRejected
) {
362 fake_delegate_
.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY
);
363 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
364 base::RunLoop().RunUntilIdle();
365 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED
, result_
);
366 EXPECT_EQ(1, fake_delegate_
.num_consent_calls());
369 TEST_F(PlatformVerificationFlowTest
, FeatureDisabled
) {
370 CrosSettings::Get()->SetBoolean(kAttestationForContentProtectionEnabled
,
372 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
373 base::RunLoop().RunUntilIdle();
374 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED
, result_
);
375 EXPECT_EQ(0, fake_delegate_
.num_consent_calls());
378 TEST_F(PlatformVerificationFlowTest
, FeatureDisabledByUser
) {
379 fake_delegate_
.pref_service().SetUserPref(prefs::kEnableDRM
,
380 new base::FundamentalValue(false));
381 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
382 base::RunLoop().RunUntilIdle();
383 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED
, result_
);
384 EXPECT_EQ(0, fake_delegate_
.num_consent_calls());
387 TEST_F(PlatformVerificationFlowTest
, FeatureDisabledByUserForDomain
) {
388 SetUserConsent(GURL(kTestURL
), false);
389 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
390 base::RunLoop().RunUntilIdle();
391 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED
, result_
);
392 EXPECT_EQ(0, fake_delegate_
.num_consent_calls());
395 TEST_F(PlatformVerificationFlowTest
, NotVerified
) {
396 certificate_success_
= false;
397 ExpectAttestationFlow();
398 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
399 base::RunLoop().RunUntilIdle();
400 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED
, result_
);
403 TEST_F(PlatformVerificationFlowTest
, ChallengeSigningError
) {
404 sign_challenge_success_
= false;
405 ExpectAttestationFlow();
406 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
407 base::RunLoop().RunUntilIdle();
408 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR
, result_
);
411 TEST_F(PlatformVerificationFlowTest
, DBusFailure
) {
412 fake_cryptohome_client_
.set_call_status(DBUS_METHOD_CALL_FAILURE
);
413 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
414 base::RunLoop().RunUntilIdle();
415 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR
, result_
);
418 TEST_F(PlatformVerificationFlowTest
, ConsentNoResponse
) {
419 fake_delegate_
.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_NONE
);
420 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
421 base::RunLoop().RunUntilIdle();
422 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED
, result_
);
425 TEST_F(PlatformVerificationFlowTest
, ConsentPerScheme
) {
426 fake_delegate_
.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY
);
427 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
428 base::RunLoop().RunUntilIdle();
429 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED
, result_
);
430 // Call again and expect denial based on previous response.
431 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
432 base::RunLoop().RunUntilIdle();
433 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED
, result_
);
434 // Call with a different scheme and expect another consent prompt.
435 fake_delegate_
.set_url(GURL(kTestURLSecure
));
436 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
437 base::RunLoop().RunUntilIdle();
438 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED
, result_
);
439 EXPECT_EQ(2, fake_delegate_
.num_consent_calls());
442 TEST_F(PlatformVerificationFlowTest
, ConsentForExtension
) {
443 fake_delegate_
.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY
);
444 fake_delegate_
.set_url(GURL(kTestURLExtension
));
445 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
446 base::RunLoop().RunUntilIdle();
447 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED
, result_
);
448 EXPECT_EQ(1, fake_delegate_
.num_consent_calls());
451 TEST_F(PlatformVerificationFlowTest
, Timeout
) {
452 verifier_
->set_timeout_delay(base::TimeDelta::FromSeconds(0));
453 ExpectAttestationFlow();
454 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
455 base::RunLoop().RunUntilIdle();
456 EXPECT_EQ(PlatformVerificationFlow::TIMEOUT
, result_
);
459 TEST_F(PlatformVerificationFlowTest
, ExpiredCert
) {
460 ExpectAttestationFlow();
461 fake_certificate_list_
.resize(2);
462 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(-1),
463 &fake_certificate_list_
[0]));
464 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(1),
465 &fake_certificate_list_
[1]));
466 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
467 base::RunLoop().RunUntilIdle();
468 EXPECT_EQ(PlatformVerificationFlow::SUCCESS
, result_
);
469 EXPECT_EQ(certificate_
, fake_certificate_list_
[1]);
472 TEST_F(PlatformVerificationFlowTest
, IncognitoMode
) {
473 fake_delegate_
.set_is_incognito(true);
474 verifier_
->ChallengePlatformKey(NULL
, kTestID
, kTestChallenge
, callback_
);
475 base::RunLoop().RunUntilIdle();
476 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED
, result_
);
479 } // namespace attestation
480 } // namespace chromeos