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 <string> 6 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/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" 29 30using testing::_; 31using testing::DoAll; 32using testing::Invoke; 33using testing::Return; 34using testing::SetArgumentPointee; 35using testing::StrictMock; 36using testing::WithArgs; 37 38namespace chromeos { 39namespace attestation { 40 41namespace { 42 43const char kTestID[] = "test_id"; 44const char kTestChallenge[] = "test_challenge"; 45const char kTestSignedData[] = "test_challenge_with_salt"; 46const char kTestSignature[] = "test_signature"; 47const char kTestCertificate[] = "test_certificate"; 48const char kTestEmail[] = "test_email@chromium.org"; 49const char kTestURL[] = "http://mytestdomain/test"; 50const char kTestURLSecure[] = "https://mytestdomain/test"; 51const char kTestURLExtension[] = "chrome-extension://mytestextension"; 52 53class FakeDelegate : public PlatformVerificationFlow::Delegate { 54 public: 55 FakeDelegate() : response_(PlatformVerificationFlow::CONSENT_RESPONSE_ALLOW), 56 num_consent_calls_(0), 57 url_(kTestURL), 58 is_incognito_(false) { 59 // Configure a user for the mock user manager. 60 mock_user_manager_.SetActiveUser(kTestEmail); 61 } 62 virtual ~FakeDelegate() {} 63 64 void SetUp() { 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); 70 } 71 72 void TearDown() { 73 content_settings_->ShutdownOnUIThread(); 74 } 75 76 virtual void ShowConsentPrompt( 77 content::WebContents* web_contents, 78 const PlatformVerificationFlow::Delegate::ConsentCallback& callback) 79 OVERRIDE { 80 num_consent_calls_++; 81 callback.Run(response_); 82 } 83 84 virtual PrefService* GetPrefs(content::WebContents* web_contents) OVERRIDE { 85 return &pref_service_; 86 } 87 88 virtual const GURL& GetURL(content::WebContents* web_contents) OVERRIDE { 89 return url_; 90 } 91 92 virtual User* GetUser(content::WebContents* web_contents) OVERRIDE { 93 return mock_user_manager_.GetActiveUser(); 94 } 95 96 virtual HostContentSettingsMap* GetContentSettings( 97 content::WebContents* web_contents) OVERRIDE { 98 return content_settings_; 99 } 100 101 virtual bool IsGuestOrIncognito(content::WebContents* web_contents) OVERRIDE { 102 return is_incognito_; 103 } 104 105 void set_response(PlatformVerificationFlow::ConsentResponse response) { 106 response_ = response; 107 } 108 109 int num_consent_calls() { 110 return num_consent_calls_; 111 } 112 113 TestingPrefServiceSyncable& pref_service() { 114 return pref_service_; 115 } 116 117 void set_url(const GURL& url) { 118 url_ = url; 119 } 120 121 void set_is_incognito(bool is_incognito) { 122 is_incognito_ = is_incognito; 123 } 124 125 private: 126 PlatformVerificationFlow::ConsentResponse response_; 127 int num_consent_calls_; 128 TestingPrefServiceSyncable pref_service_; 129 MockUserManager mock_user_manager_; 130 GURL url_; 131 scoped_refptr<HostContentSettingsMap> content_settings_; 132 bool is_incognito_; 133 134 DISALLOW_COPY_AND_ASSIGN(FakeDelegate); 135}; 136 137class CustomFakeCryptohomeClient : public FakeCryptohomeClient { 138 public: 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, 145 base::Bind(callback, 146 call_status_, 147 attestation_enrolled_)); 148 } 149 150 virtual void TpmAttestationIsPrepared( 151 const BoolDBusMethodCallback& callback) OVERRIDE { 152 base::MessageLoop::current()->PostTask(FROM_HERE, 153 base::Bind(callback, 154 call_status_, 155 attestation_prepared_)); 156 } 157 158 void set_call_status(DBusMethodCallStatus call_status) { 159 call_status_ = call_status; 160 } 161 162 void set_attestation_enrolled(bool attestation_enrolled) { 163 attestation_enrolled_ = attestation_enrolled; 164 } 165 166 void set_attestation_prepared(bool attestation_prepared) { 167 attestation_prepared_ = attestation_prepared; 168 } 169 170 private: 171 DBusMethodCallStatus call_status_; 172 bool attestation_enrolled_; 173 bool attestation_prepared_; 174}; 175 176} // namespace 177 178class PlatformVerificationFlowTest : public ::testing::Test { 179 public: 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) {} 186 187 void SetUp() { 188 fake_delegate_.SetUp(); 189 190 // Create a verifier for tests to call. 191 verifier_ = new PlatformVerificationFlow(&mock_attestation_flow_, 192 &mock_async_caller_, 193 &fake_cryptohome_client_, 194 &fake_delegate_); 195 196 // Create callbacks for tests to use with verifier_. 197 callback_ = base::Bind(&PlatformVerificationFlowTest::FakeChallengeCallback, 198 base::Unretained(this)); 199 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); 207 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)); 211 212 } 213 214 void TearDown() { 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(); 220 } 221 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. 226 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))); 233 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, 239 expected_key_name, 240 kTestChallenge, _)) 241 .WillRepeatedly(WithArgs<4>(Invoke( 242 this, &PlatformVerificationFlowTest::FakeSignChallenge))); 243 } 244 245 void SetUserConsent(const GURL& url, bool allow) { 246 verifier_->RecordDomainConsent(fake_delegate_.GetContentSettings(NULL), 247 url, 248 allow); 249 } 250 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, 257 base::Bind(callback, 258 certificate_success_, 259 certificate)); 260 ++fake_certificate_index_; 261 } 262 263 void FakeSignChallenge( 264 const cryptohome::AsyncMethodCaller::DataCallback& callback) { 265 base::MessageLoop::current()->PostTask( 266 FROM_HERE, 267 base::Bind(callback, 268 sign_challenge_success_, 269 CreateFakeResponseProto())); 270 } 271 272 void FakeChallengeCallback(PlatformVerificationFlow::Result result, 273 const std::string& salt, 274 const std::string& signature, 275 const std::string& certificate) { 276 result_ = result; 277 challenge_salt_ = salt; 278 challenge_signature_ = signature; 279 certificate_ = certificate; 280 } 281 282 std::string CreateFakeResponseProto() { 283 SignedData pb; 284 pb.set_data(kTestSignedData); 285 pb.set_signature(kTestSignature); 286 std::string serial; 287 CHECK(pb.SerializeToString(&serial)); 288 return serial; 289 } 290 291 protected: 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_; 303 304 // Controls result of FakeGetCertificate. 305 bool certificate_success_; 306 std::vector<std::string> fake_certificate_list_; 307 size_t fake_certificate_index_; 308 309 // Controls result of FakeSignChallenge. 310 bool sign_challenge_success_; 311 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_; 318}; 319 320TEST_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()); 332} 333 334TEST_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()); 345} 346 347TEST_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()); 359} 360 361TEST_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()); 367} 368 369TEST_F(PlatformVerificationFlowTest, FeatureDisabled) { 370 CrosSettings::Get()->SetBoolean(kAttestationForContentProtectionEnabled, 371 false); 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()); 376} 377 378TEST_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()); 385} 386 387TEST_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()); 393} 394 395TEST_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_); 401} 402 403TEST_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_); 409} 410 411TEST_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_); 416} 417 418TEST_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_); 423} 424 425TEST_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()); 440} 441 442TEST_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()); 449} 450 451TEST_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_); 457} 458 459TEST_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]); 470} 471 472TEST_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_); 477} 478 479} // namespace attestation 480} // namespace chromeos 481