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/pref_names.h" 21#include "chrome/test/base/testing_pref_service_syncable.h" 22#include "chromeos/attestation/mock_attestation_flow.h" 23#include "chromeos/cryptohome/mock_async_method_caller.h" 24#include "chromeos/dbus/fake_cryptohome_client.h" 25#include "chromeos/settings/cros_settings_names.h" 26#include "components/content_settings/core/common/content_settings_pattern.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_manager::User* GetUser( 93 content::WebContents* web_contents) OVERRIDE { 94 return mock_user_manager_.GetActiveUser(); 95 } 96 97 virtual HostContentSettingsMap* GetContentSettings( 98 content::WebContents* web_contents) OVERRIDE { 99 return content_settings_.get(); 100 } 101 102 virtual bool IsGuestOrIncognito(content::WebContents* web_contents) OVERRIDE { 103 return is_incognito_; 104 } 105 106 void set_response(PlatformVerificationFlow::ConsentResponse response) { 107 response_ = response; 108 } 109 110 int num_consent_calls() { 111 return num_consent_calls_; 112 } 113 114 TestingPrefServiceSyncable& pref_service() { 115 return pref_service_; 116 } 117 118 void set_url(const GURL& url) { 119 url_ = url; 120 } 121 122 void set_is_incognito(bool is_incognito) { 123 is_incognito_ = is_incognito; 124 } 125 126 private: 127 PlatformVerificationFlow::ConsentResponse response_; 128 int num_consent_calls_; 129 TestingPrefServiceSyncable pref_service_; 130 MockUserManager mock_user_manager_; 131 GURL url_; 132 scoped_refptr<HostContentSettingsMap> content_settings_; 133 bool is_incognito_; 134 135 DISALLOW_COPY_AND_ASSIGN(FakeDelegate); 136}; 137 138class CustomFakeCryptohomeClient : public FakeCryptohomeClient { 139 public: 140 CustomFakeCryptohomeClient() : call_status_(DBUS_METHOD_CALL_SUCCESS), 141 attestation_enrolled_(true), 142 attestation_prepared_(true) {} 143 virtual void TpmAttestationIsEnrolled( 144 const BoolDBusMethodCallback& callback) OVERRIDE { 145 base::MessageLoop::current()->PostTask(FROM_HERE, 146 base::Bind(callback, 147 call_status_, 148 attestation_enrolled_)); 149 } 150 151 virtual void TpmAttestationIsPrepared( 152 const BoolDBusMethodCallback& callback) OVERRIDE { 153 base::MessageLoop::current()->PostTask(FROM_HERE, 154 base::Bind(callback, 155 call_status_, 156 attestation_prepared_)); 157 } 158 159 void set_call_status(DBusMethodCallStatus call_status) { 160 call_status_ = call_status; 161 } 162 163 void set_attestation_enrolled(bool attestation_enrolled) { 164 attestation_enrolled_ = attestation_enrolled; 165 } 166 167 void set_attestation_prepared(bool attestation_prepared) { 168 attestation_prepared_ = attestation_prepared; 169 } 170 171 private: 172 DBusMethodCallStatus call_status_; 173 bool attestation_enrolled_; 174 bool attestation_prepared_; 175}; 176 177} // namespace 178 179class PlatformVerificationFlowTest : public ::testing::Test { 180 public: 181 PlatformVerificationFlowTest() 182 : ui_thread_(content::BrowserThread::UI, &message_loop_), 183 certificate_success_(true), 184 fake_certificate_index_(0), 185 sign_challenge_success_(true), 186 result_(PlatformVerificationFlow::INTERNAL_ERROR) {} 187 188 void SetUp() { 189 fake_delegate_.SetUp(); 190 191 // Create a verifier for tests to call. 192 verifier_ = new PlatformVerificationFlow(&mock_attestation_flow_, 193 &mock_async_caller_, 194 &fake_cryptohome_client_, 195 &fake_delegate_); 196 197 // Create callbacks for tests to use with verifier_. 198 callback_ = base::Bind(&PlatformVerificationFlowTest::FakeChallengeCallback, 199 base::Unretained(this)); 200 201 // Configure the global cros_settings. 202 CrosSettings* cros_settings = CrosSettings::Get(); 203 device_settings_provider_ = 204 cros_settings->GetProvider(kAttestationForContentProtectionEnabled); 205 cros_settings->RemoveSettingsProvider(device_settings_provider_); 206 cros_settings->AddSettingsProvider(&stub_settings_provider_); 207 cros_settings->SetBoolean(kAttestationForContentProtectionEnabled, true); 208 209 // Start with the first-time setting set since most tests want this. 210 fake_delegate_.pref_service().SetUserPref(prefs::kRAConsentFirstTime, 211 new base::FundamentalValue(true)); 212 213 } 214 215 void TearDown() { 216 // Restore the real DeviceSettingsProvider. 217 CrosSettings* cros_settings = CrosSettings::Get(); 218 cros_settings->RemoveSettingsProvider(&stub_settings_provider_); 219 cros_settings->AddSettingsProvider(device_settings_provider_); 220 fake_delegate_.TearDown(); 221 } 222 223 void ExpectAttestationFlow() { 224 // When consent is not given or the feature is disabled, it is important 225 // that there are no calls to the attestation service. Thus, a test must 226 // explicitly expect these calls or the mocks will fail the test. 227 228 // Configure the mock AttestationFlow to call FakeGetCertificate. 229 EXPECT_CALL(mock_attestation_flow_, 230 GetCertificate(PROFILE_CONTENT_PROTECTION_CERTIFICATE, 231 kTestEmail, kTestID, _, _)) 232 .WillRepeatedly(WithArgs<4>(Invoke( 233 this, &PlatformVerificationFlowTest::FakeGetCertificate))); 234 235 // Configure the mock AsyncMethodCaller to call FakeSignChallenge. 236 std::string expected_key_name = std::string(kContentProtectionKeyPrefix) + 237 std::string(kTestID); 238 EXPECT_CALL(mock_async_caller_, 239 TpmAttestationSignSimpleChallenge(KEY_USER, kTestEmail, 240 expected_key_name, 241 kTestChallenge, _)) 242 .WillRepeatedly(WithArgs<4>(Invoke( 243 this, &PlatformVerificationFlowTest::FakeSignChallenge))); 244 } 245 246 void SetUserConsent(const GURL& url, bool allow) { 247 verifier_->RecordDomainConsent(fake_delegate_.GetContentSettings(NULL), 248 url, 249 allow); 250 } 251 252 void FakeGetCertificate( 253 const AttestationFlow::CertificateCallback& callback) { 254 std::string certificate = 255 (fake_certificate_index_ < fake_certificate_list_.size()) ? 256 fake_certificate_list_[fake_certificate_index_] : kTestCertificate; 257 base::MessageLoop::current()->PostTask(FROM_HERE, 258 base::Bind(callback, 259 certificate_success_, 260 certificate)); 261 ++fake_certificate_index_; 262 } 263 264 void FakeSignChallenge( 265 const cryptohome::AsyncMethodCaller::DataCallback& callback) { 266 base::MessageLoop::current()->PostTask( 267 FROM_HERE, 268 base::Bind(callback, 269 sign_challenge_success_, 270 CreateFakeResponseProto())); 271 } 272 273 void FakeChallengeCallback(PlatformVerificationFlow::Result result, 274 const std::string& salt, 275 const std::string& signature, 276 const std::string& certificate) { 277 result_ = result; 278 challenge_salt_ = salt; 279 challenge_signature_ = signature; 280 certificate_ = certificate; 281 } 282 283 std::string CreateFakeResponseProto() { 284 SignedData pb; 285 pb.set_data(kTestSignedData); 286 pb.set_signature(kTestSignature); 287 std::string serial; 288 CHECK(pb.SerializeToString(&serial)); 289 return serial; 290 } 291 292 protected: 293 base::MessageLoopForUI message_loop_; 294 content::TestBrowserThread ui_thread_; 295 StrictMock<MockAttestationFlow> mock_attestation_flow_; 296 cryptohome::MockAsyncMethodCaller mock_async_caller_; 297 CustomFakeCryptohomeClient fake_cryptohome_client_; 298 FakeDelegate fake_delegate_; 299 CrosSettingsProvider* device_settings_provider_; 300 StubCrosSettingsProvider stub_settings_provider_; 301 ScopedTestDeviceSettingsService test_device_settings_service_; 302 ScopedTestCrosSettings test_cros_settings_; 303 scoped_refptr<PlatformVerificationFlow> verifier_; 304 305 // Controls result of FakeGetCertificate. 306 bool certificate_success_; 307 std::vector<std::string> fake_certificate_list_; 308 size_t fake_certificate_index_; 309 310 // Controls result of FakeSignChallenge. 311 bool sign_challenge_success_; 312 313 // Callback functions and data. 314 PlatformVerificationFlow::ChallengeCallback callback_; 315 PlatformVerificationFlow::Result result_; 316 std::string challenge_salt_; 317 std::string challenge_signature_; 318 std::string certificate_; 319}; 320 321TEST_F(PlatformVerificationFlowTest, SuccessNoConsent) { 322 SetUserConsent(GURL(kTestURL), true); 323 // Make sure the call will fail if consent is requested. 324 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY); 325 ExpectAttestationFlow(); 326 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 327 base::RunLoop().RunUntilIdle(); 328 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_); 329 EXPECT_EQ(kTestSignedData, challenge_salt_); 330 EXPECT_EQ(kTestSignature, challenge_signature_); 331 EXPECT_EQ(kTestCertificate, certificate_); 332 EXPECT_EQ(0, fake_delegate_.num_consent_calls()); 333} 334 335TEST_F(PlatformVerificationFlowTest, SuccessWithAttestationConsent) { 336 SetUserConsent(GURL(kTestURL), true); 337 fake_cryptohome_client_.set_attestation_enrolled(false); 338 ExpectAttestationFlow(); 339 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 340 base::RunLoop().RunUntilIdle(); 341 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_); 342 EXPECT_EQ(kTestSignedData, challenge_salt_); 343 EXPECT_EQ(kTestSignature, challenge_signature_); 344 EXPECT_EQ(kTestCertificate, certificate_); 345 EXPECT_EQ(1, fake_delegate_.num_consent_calls()); 346} 347 348TEST_F(PlatformVerificationFlowTest, SuccessWithFirstTimeConsent) { 349 SetUserConsent(GURL(kTestURL), true); 350 fake_delegate_.pref_service().SetUserPref(prefs::kRAConsentFirstTime, 351 new base::FundamentalValue(false)); 352 ExpectAttestationFlow(); 353 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 354 base::RunLoop().RunUntilIdle(); 355 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_); 356 EXPECT_EQ(kTestSignedData, challenge_salt_); 357 EXPECT_EQ(kTestSignature, challenge_signature_); 358 EXPECT_EQ(kTestCertificate, certificate_); 359 EXPECT_EQ(1, fake_delegate_.num_consent_calls()); 360} 361 362TEST_F(PlatformVerificationFlowTest, ConsentRejected) { 363 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY); 364 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 365 base::RunLoop().RunUntilIdle(); 366 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_); 367 EXPECT_EQ(1, fake_delegate_.num_consent_calls()); 368} 369 370TEST_F(PlatformVerificationFlowTest, FeatureDisabled) { 371 CrosSettings::Get()->SetBoolean(kAttestationForContentProtectionEnabled, 372 false); 373 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 374 base::RunLoop().RunUntilIdle(); 375 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_); 376 EXPECT_EQ(0, fake_delegate_.num_consent_calls()); 377} 378 379TEST_F(PlatformVerificationFlowTest, FeatureDisabledByUser) { 380 fake_delegate_.pref_service().SetUserPref(prefs::kEnableDRM, 381 new base::FundamentalValue(false)); 382 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 383 base::RunLoop().RunUntilIdle(); 384 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_); 385 EXPECT_EQ(0, fake_delegate_.num_consent_calls()); 386} 387 388TEST_F(PlatformVerificationFlowTest, FeatureDisabledByUserForDomain) { 389 SetUserConsent(GURL(kTestURL), false); 390 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 391 base::RunLoop().RunUntilIdle(); 392 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_); 393 EXPECT_EQ(0, fake_delegate_.num_consent_calls()); 394} 395 396TEST_F(PlatformVerificationFlowTest, NotVerified) { 397 certificate_success_ = false; 398 ExpectAttestationFlow(); 399 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 400 base::RunLoop().RunUntilIdle(); 401 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_); 402} 403 404TEST_F(PlatformVerificationFlowTest, ChallengeSigningError) { 405 sign_challenge_success_ = false; 406 ExpectAttestationFlow(); 407 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 408 base::RunLoop().RunUntilIdle(); 409 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_); 410} 411 412TEST_F(PlatformVerificationFlowTest, DBusFailure) { 413 fake_cryptohome_client_.set_call_status(DBUS_METHOD_CALL_FAILURE); 414 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 415 base::RunLoop().RunUntilIdle(); 416 EXPECT_EQ(PlatformVerificationFlow::INTERNAL_ERROR, result_); 417} 418 419TEST_F(PlatformVerificationFlowTest, ConsentNoResponse) { 420 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_NONE); 421 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 422 base::RunLoop().RunUntilIdle(); 423 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_); 424} 425 426TEST_F(PlatformVerificationFlowTest, ConsentPerScheme) { 427 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY); 428 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 429 base::RunLoop().RunUntilIdle(); 430 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_); 431 // Call again and expect denial based on previous response. 432 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 433 base::RunLoop().RunUntilIdle(); 434 EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_); 435 // Call with a different scheme and expect another consent prompt. 436 fake_delegate_.set_url(GURL(kTestURLSecure)); 437 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 438 base::RunLoop().RunUntilIdle(); 439 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_); 440 EXPECT_EQ(2, fake_delegate_.num_consent_calls()); 441} 442 443TEST_F(PlatformVerificationFlowTest, ConsentForExtension) { 444 fake_delegate_.set_response(PlatformVerificationFlow::CONSENT_RESPONSE_DENY); 445 fake_delegate_.set_url(GURL(kTestURLExtension)); 446 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 447 base::RunLoop().RunUntilIdle(); 448 EXPECT_EQ(PlatformVerificationFlow::USER_REJECTED, result_); 449 EXPECT_EQ(1, fake_delegate_.num_consent_calls()); 450} 451 452TEST_F(PlatformVerificationFlowTest, Timeout) { 453 verifier_->set_timeout_delay(base::TimeDelta::FromSeconds(0)); 454 ExpectAttestationFlow(); 455 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 456 base::RunLoop().RunUntilIdle(); 457 EXPECT_EQ(PlatformVerificationFlow::TIMEOUT, result_); 458} 459 460TEST_F(PlatformVerificationFlowTest, ExpiredCert) { 461 ExpectAttestationFlow(); 462 fake_certificate_list_.resize(2); 463 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(-1), 464 &fake_certificate_list_[0])); 465 ASSERT_TRUE(GetFakeCertificate(base::TimeDelta::FromDays(1), 466 &fake_certificate_list_[1])); 467 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 468 base::RunLoop().RunUntilIdle(); 469 EXPECT_EQ(PlatformVerificationFlow::SUCCESS, result_); 470 EXPECT_EQ(certificate_, fake_certificate_list_[1]); 471} 472 473TEST_F(PlatformVerificationFlowTest, IncognitoMode) { 474 fake_delegate_.set_is_incognito(true); 475 verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); 476 base::RunLoop().RunUntilIdle(); 477 EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_); 478} 479 480} // namespace attestation 481} // namespace chromeos 482