1 // Copyright 2020 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 "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h"
6
7 #include "base/bind.h"
8 #include "base/optional.h"
9 #include "base/run_loop.h"
10 #include "base/test/gmock_callback_support.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/chromeos/attestation/mock_machine_certificate_uploader.h"
13 #include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h"
14 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
15 #include "chrome/browser/chromeos/platform_keys/key_permissions/fake_user_private_token_kpm_service.h"
16 #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_impl.h"
17 #include "chrome/browser/chromeos/platform_keys/key_permissions/mock_key_permissions_manager.h"
18 #include "chrome/browser/chromeos/platform_keys/key_permissions/user_private_token_kpm_service_factory.h"
19 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #include "chrome/common/chrome_constants.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/testing_profile_manager.h"
26 #include "chromeos/attestation/mock_attestation_flow.h"
27 #include "chromeos/cryptohome/cryptohome_parameters.h"
28 #include "chromeos/dbus/attestation/fake_attestation_client.h"
29 #include "chromeos/dbus/attestation/interface.pb.h"
30 #include "chromeos/dbus/constants/attestation_constants.h"
31 #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h"
32 #include "components/prefs/pref_service.h"
33 #include "components/sync_preferences/testing_pref_service_syncable.h"
34 #include "content/public/test/browser_task_environment.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 using base::test::RunOnceCallback;
38 using testing::_;
39 using testing::Invoke;
40 using testing::StrictMock;
41
42 namespace chromeos {
43 namespace attestation {
44 namespace {
45
46 constexpr char kTestUserEmail[] = "test@google.com";
47 constexpr char kTestUserDomain[] = "google.com";
48 constexpr char kTestUserGaiaId[] = "test_gaia_id";
49 constexpr char kEmptyKeyName[] = "";
50 constexpr char kNonDefaultKeyName[] = "key_name_123";
51 constexpr char kFakeCertificate[] = "fake_cert";
52
GetDefaultKeyName(AttestationKeyType type)53 const char* GetDefaultKeyName(AttestationKeyType type) {
54 switch (type) {
55 case KEY_DEVICE:
56 return kEnterpriseMachineKey;
57 case KEY_USER:
58 return kEnterpriseUserKey;
59 }
60 }
61
GetChallenge()62 std::string GetChallenge() {
63 constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'c', 'h',
64 'a', 'l', 0xfd, 0xfe, 0xff};
65 return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer));
66 }
67
GetChallengeResponse(bool include_spkac)68 std::string GetChallengeResponse(bool include_spkac) {
69 return AttestationClient::Get()
70 ->GetTestInterface()
71 ->GetEnterpriseChallengeFakeSignature(GetChallenge(), include_spkac);
72 }
73
GetPublicKey()74 std::string GetPublicKey() {
75 constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'p', 'u',
76 'b', 'k', 0xfd, 0xfe, 0xff};
77 return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer));
78 }
79
80 class CallbackObserver {
81 public:
GetCallback()82 TpmChallengeKeyCallback GetCallback() {
83 return base::BindOnce(&CallbackObserver::Callback, base::Unretained(this));
84 }
85
IsResultReceived() const86 bool IsResultReceived() const { return result_.has_value(); }
87
GetResult() const88 const TpmChallengeKeyResult& GetResult() const {
89 CHECK(result_.has_value()) << "Callback was never called";
90 return result_.value();
91 }
92
WaitForCallback()93 void WaitForCallback() { loop_.Run(); }
94
95 private:
Callback(const TpmChallengeKeyResult & result)96 void Callback(const TpmChallengeKeyResult& result) {
97 CHECK(!result_.has_value()) << "Callback was called more than once";
98 result_ = result;
99 loop_.Quit();
100 }
101
102 base::RunLoop loop_;
103 base::Optional<TpmChallengeKeyResult> result_;
104 };
105
106 template <typename T>
107 struct CallbackHolder {
SaveCallbackchromeos::attestation::__anon30802b6f0111::CallbackHolder108 void SaveCallback(T new_callback) {
109 CHECK(callback.is_null());
110 callback = std::move(new_callback);
111 }
112
113 T callback;
114 };
115
116 //================= MockableFakeAttestationFlow ================================
117
118 class MockableFakeAttestationFlow : public MockAttestationFlow {
119 public:
MockableFakeAttestationFlow()120 MockableFakeAttestationFlow() {
121 ON_CALL(*this, GetCertificate(_, _, _, _, _, _))
122 .WillByDefault(
123 Invoke(this, &MockableFakeAttestationFlow::GetCertificateInternal));
124 }
125 ~MockableFakeAttestationFlow() override = default;
set_status(AttestationStatus status)126 void set_status(AttestationStatus status) { status_ = status; }
127
128 private:
GetCertificateInternal(AttestationCertificateProfile,const AccountId & account_id,const std::string &,bool,const std::string & key_name,CertificateCallback callback)129 void GetCertificateInternal(
130 AttestationCertificateProfile /*certificate_profile*/,
131 const AccountId& account_id,
132 const std::string& /*request_origin*/,
133 bool /*force_new_key*/,
134 const std::string& key_name,
135 CertificateCallback callback) {
136 std::string certificate;
137 if (status_ == ATTESTATION_SUCCESS) {
138 certificate = certificate_;
139 AttestationClient::Get()
140 ->GetTestInterface()
141 ->GetMutableKeyInfoReply(cryptohome::Identification(account_id).id(),
142 key_name)
143 ->set_public_key(public_key_);
144 }
145 std::move(callback).Run(status_, certificate);
146 }
147 AttestationStatus status_ = ATTESTATION_SUCCESS;
148 const std::string certificate_ = kFakeCertificate;
149 const std::string public_key_ = GetPublicKey();
150 };
151
152 //================== TpmChallengeKeySubtleTest =================================
153
154 class TpmChallengeKeySubtleTest : public ::testing::Test {
155 public:
156 TpmChallengeKeySubtleTest();
157 ~TpmChallengeKeySubtleTest();
158
159 protected:
160 void InitSigninProfile();
161 void InitUnaffiliatedProfile();
162 void InitAffiliatedProfile();
163 void InitAfterProfileCreated();
164
165 TestingProfile* CreateUserProfile(bool is_affiliated);
166 TestingProfile* GetProfile();
167 chromeos::ScopedCrosSettingsTestHelper* GetCrosSettingsHelper();
168 chromeos::StubInstallAttributes* GetInstallAttributes();
169
170 // Runs StartPrepareKeyStep and checks that the result is equal to
171 // |public_key|.
172 void RunOneStepAndExpect(AttestationKeyType key_type,
173 bool will_register_key,
174 const std::string& key_name,
175 const TpmChallengeKeyResult& public_key);
176 // Runs StartPrepareKeyStep and checks that the result is success. Then runs
177 // StartSignChallengeStep and checks that the result is equal to
178 // |challenge_response|.
179 void RunTwoStepsAndExpect(AttestationKeyType key_type,
180 bool will_register_key,
181 const std::string& key_name,
182 const TpmChallengeKeyResult& challenge_response);
183 // Runs first two steps and checks that results are success. Then runs
184 // StartRegisterKeyStep and checks that the result is equal to
185 // |register_result|.
186 void RunThreeStepsAndExpect(AttestationKeyType key_type,
187 bool will_register_key,
188 const std::string& key_name,
189 const TpmChallengeKeyResult& register_result);
190
191 content::BrowserTaskEnvironment task_environment_{
192 base::test::TaskEnvironment::TimeSource::MOCK_TIME};
193
194 StrictMock<MockableFakeAttestationFlow> mock_attestation_flow_;
195 chromeos::FakeCryptohomeClient cryptohome_client_;
196 std::unique_ptr<platform_keys::MockKeyPermissionsManager>
197 system_token_key_permissions_manager_;
198 std::unique_ptr<platform_keys::MockKeyPermissionsManager>
199 user_private_token_key_permissions_manager_;
200 MockMachineCertificateUploader mock_cert_uploader_;
201
202 TestingProfileManager testing_profile_manager_;
203 chromeos::FakeChromeUserManager fake_user_manager_;
204 TestingProfile* testing_profile_ = nullptr;
205
206 std::unique_ptr<TpmChallengeKeySubtle> challenge_key_subtle_;
207 };
208
TpmChallengeKeySubtleTest()209 TpmChallengeKeySubtleTest::TpmChallengeKeySubtleTest()
210 : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {
211 ::chromeos::AttestationClient::InitializeFake();
212 CHECK(testing_profile_manager_.SetUp());
213
214 challenge_key_subtle_ = std::make_unique<TpmChallengeKeySubtleImpl>(
215 &mock_attestation_flow_, &mock_cert_uploader_);
216
217 // By default make it reply that the certificate is already uploaded.
218 ON_CALL(mock_cert_uploader_, WaitForUploadComplete)
219 .WillByDefault(RunOnceCallback<0>(true));
220 }
221
~TpmChallengeKeySubtleTest()222 TpmChallengeKeySubtleTest::~TpmChallengeKeySubtleTest() {
223 ::chromeos::AttestationClient::Shutdown();
224 }
225
InitSigninProfile()226 void TpmChallengeKeySubtleTest::InitSigninProfile() {
227 testing_profile_ =
228 testing_profile_manager_.CreateTestingProfile(chrome::kInitialProfile);
229 InitAfterProfileCreated();
230 }
231
InitUnaffiliatedProfile()232 void TpmChallengeKeySubtleTest::InitUnaffiliatedProfile() {
233 testing_profile_ = CreateUserProfile(/*is_affiliated=*/false);
234 InitAfterProfileCreated();
235 }
236
InitAffiliatedProfile()237 void TpmChallengeKeySubtleTest::InitAffiliatedProfile() {
238 testing_profile_ = CreateUserProfile(/*is_affiliated=*/true);
239 InitAfterProfileCreated();
240 GetProfile()->GetTestingPrefService()->SetManagedPref(
241 prefs::kAttestationEnabled, std::make_unique<base::Value>(true));
242 }
243
InitAfterProfileCreated()244 void TpmChallengeKeySubtleTest::InitAfterProfileCreated() {
245 GetInstallAttributes()->SetCloudManaged("google.com", "device_id");
246
247 GetCrosSettingsHelper()->ReplaceDeviceSettingsProviderWithStub();
248 GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled,
249 true);
250
251 user_private_token_key_permissions_manager_ =
252 std::make_unique<platform_keys::MockKeyPermissionsManager>();
253 platform_keys::UserPrivateTokenKeyPermissionsManagerServiceFactory::
254 GetInstance()
255 ->SetTestingFactory(
256 GetProfile(),
257 base::BindRepeating(
258 &platform_keys::
259 BuildFakeUserPrivateTokenKeyPermissionsManagerService,
260 user_private_token_key_permissions_manager_.get()));
261
262 system_token_key_permissions_manager_ =
263 std::make_unique<platform_keys::MockKeyPermissionsManager>();
264 platform_keys::KeyPermissionsManagerImpl::
265 SetSystemTokenKeyPermissionsManagerForTesting(
266 system_token_key_permissions_manager_.get());
267 }
268
CreateUserProfile(bool is_affiliated)269 TestingProfile* TpmChallengeKeySubtleTest::CreateUserProfile(
270 bool is_affiliated) {
271 TestingProfile* testing_profile =
272 testing_profile_manager_.CreateTestingProfile(kTestUserEmail);
273 CHECK(testing_profile);
274
275 auto test_account =
276 AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId);
277 fake_user_manager_.AddUserWithAffiliation(test_account, is_affiliated);
278
279 chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
280 fake_user_manager_.GetPrimaryUser(), testing_profile);
281
282 return testing_profile;
283 }
284
GetProfile()285 TestingProfile* TpmChallengeKeySubtleTest::GetProfile() {
286 return testing_profile_;
287 }
288
289 chromeos::ScopedCrosSettingsTestHelper*
GetCrosSettingsHelper()290 TpmChallengeKeySubtleTest::GetCrosSettingsHelper() {
291 return GetProfile()->ScopedCrosSettingsTestHelper();
292 }
293
294 chromeos::StubInstallAttributes*
GetInstallAttributes()295 TpmChallengeKeySubtleTest::GetInstallAttributes() {
296 return GetCrosSettingsHelper()->InstallAttributes();
297 }
298
RunOneStepAndExpect(AttestationKeyType key_type,bool will_register_key,const std::string & key_name,const TpmChallengeKeyResult & public_key)299 void TpmChallengeKeySubtleTest::RunOneStepAndExpect(
300 AttestationKeyType key_type,
301 bool will_register_key,
302 const std::string& key_name,
303 const TpmChallengeKeyResult& public_key) {
304 CallbackObserver callback_observer;
305 challenge_key_subtle_->StartPrepareKeyStep(key_type, will_register_key,
306 key_name, GetProfile(),
307 callback_observer.GetCallback());
308 callback_observer.WaitForCallback();
309
310 EXPECT_EQ(callback_observer.GetResult(), public_key);
311 }
312
RunTwoStepsAndExpect(AttestationKeyType key_type,bool will_register_key,const std::string & key_name,const TpmChallengeKeyResult & challenge_response)313 void TpmChallengeKeySubtleTest::RunTwoStepsAndExpect(
314 AttestationKeyType key_type,
315 bool will_register_key,
316 const std::string& key_name,
317 const TpmChallengeKeyResult& challenge_response) {
318 RunOneStepAndExpect(key_type, will_register_key, key_name,
319 TpmChallengeKeyResult::MakePublicKey(GetPublicKey()));
320
321 CallbackObserver callback_observer;
322 challenge_key_subtle_->StartSignChallengeStep(
323 GetChallenge(), callback_observer.GetCallback());
324 callback_observer.WaitForCallback();
325
326 EXPECT_EQ(callback_observer.GetResult(), challenge_response);
327 }
328
RunThreeStepsAndExpect(AttestationKeyType key_type,bool will_register_key,const std::string & key_name,const TpmChallengeKeyResult & register_result)329 void TpmChallengeKeySubtleTest::RunThreeStepsAndExpect(
330 AttestationKeyType key_type,
331 bool will_register_key,
332 const std::string& key_name,
333 const TpmChallengeKeyResult& register_result) {
334 RunTwoStepsAndExpect(key_type, will_register_key, key_name,
335 TpmChallengeKeyResult::MakeChallengeResponse(
336 GetChallengeResponse(will_register_key)));
337
338 CallbackObserver callback_observer;
339 challenge_key_subtle_->StartRegisterKeyStep(callback_observer.GetCallback());
340 callback_observer.WaitForCallback();
341
342 EXPECT_EQ(callback_observer.GetResult(), register_result);
343 }
344
345 //==============================================================================
346
TEST_F(TpmChallengeKeySubtleTest,DeviceKeyNonEnterpriseDevice)347 TEST_F(TpmChallengeKeySubtleTest, DeviceKeyNonEnterpriseDevice) {
348 InitSigninProfile();
349
350 GetInstallAttributes()->SetConsumerOwned();
351
352 RunOneStepAndExpect(
353 KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
354 TpmChallengeKeyResult::MakeError(
355 TpmChallengeKeyResultCode::kNonEnterpriseDeviceError));
356 }
357
TEST_F(TpmChallengeKeySubtleTest,DeviceKeyDeviceAttestationDisabled)358 TEST_F(TpmChallengeKeySubtleTest, DeviceKeyDeviceAttestationDisabled) {
359 InitSigninProfile();
360
361 GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled,
362 false);
363
364 RunOneStepAndExpect(
365 KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
366 TpmChallengeKeyResult::MakeError(
367 TpmChallengeKeyResultCode::kDevicePolicyDisabledError));
368 }
369
TEST_F(TpmChallengeKeySubtleTest,DeviceKeyUserNotManaged)370 TEST_F(TpmChallengeKeySubtleTest, DeviceKeyUserNotManaged) {
371 InitUnaffiliatedProfile();
372
373 RunOneStepAndExpect(KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
374 TpmChallengeKeyResult::MakeError(
375 TpmChallengeKeyResultCode::kUserNotManagedError));
376 }
377
TEST_F(TpmChallengeKeySubtleTest,UserKeyUserKeyNotAvailable)378 TEST_F(TpmChallengeKeySubtleTest, UserKeyUserKeyNotAvailable) {
379 InitSigninProfile();
380
381 RunOneStepAndExpect(
382 KEY_USER, /*will_register_key=*/false, kEmptyKeyName,
383 TpmChallengeKeyResult::MakeError(
384 TpmChallengeKeyResultCode::kUserKeyNotAvailableError));
385 }
386
TEST_F(TpmChallengeKeySubtleTest,UserKeyUserPolicyDisabled)387 TEST_F(TpmChallengeKeySubtleTest, UserKeyUserPolicyDisabled) {
388 InitAffiliatedProfile();
389 GetProfile()->GetTestingPrefService()->SetManagedPref(
390 prefs::kAttestationEnabled, std::make_unique<base::Value>(false));
391
392 RunOneStepAndExpect(KEY_USER, /*will_register_key=*/false, kEmptyKeyName,
393 TpmChallengeKeyResult::MakeError(
394 TpmChallengeKeyResultCode::kUserPolicyDisabledError));
395 }
396
397 // Checks that a user should be affiliated with a device
TEST_F(TpmChallengeKeySubtleTest,UserKeyUserNotAffiliated)398 TEST_F(TpmChallengeKeySubtleTest, UserKeyUserNotAffiliated) {
399 InitUnaffiliatedProfile();
400 GetProfile()->GetTestingPrefService()->SetManagedPref(
401 prefs::kAttestationEnabled, std::make_unique<base::Value>(true));
402
403 RunOneStepAndExpect(KEY_USER, /*will_register_key=*/false, kEmptyKeyName,
404 TpmChallengeKeyResult::MakeError(
405 TpmChallengeKeyResultCode::kUserNotManagedError));
406 }
407
TEST_F(TpmChallengeKeySubtleTest,UserKeyDeviceAttestationDisabled)408 TEST_F(TpmChallengeKeySubtleTest, UserKeyDeviceAttestationDisabled) {
409 InitAffiliatedProfile();
410 GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled,
411 false);
412
413 RunOneStepAndExpect(
414 KEY_USER, /*will_register_key=*/false, kEmptyKeyName,
415 TpmChallengeKeyResult::MakeError(
416 TpmChallengeKeyResultCode::kDevicePolicyDisabledError));
417 }
418
TEST_F(TpmChallengeKeySubtleTest,DoesKeyExistDbusFailed)419 TEST_F(TpmChallengeKeySubtleTest, DoesKeyExistDbusFailed) {
420 InitSigninProfile();
421
422 AttestationClient::Get()
423 ->GetTestInterface()
424 ->GetMutableKeyInfoReply(/*username=*/"", kEnterpriseMachineKey)
425 ->set_status(::attestation::STATUS_DBUS_ERROR);
426
427 RunOneStepAndExpect(
428 KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
429 TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError));
430 }
431
TEST_F(TpmChallengeKeySubtleTest,GetCertificateFailed)432 TEST_F(TpmChallengeKeySubtleTest, GetCertificateFailed) {
433 InitSigninProfile();
434 const AttestationKeyType key_type = KEY_DEVICE;
435
436 mock_attestation_flow_.set_status(ATTESTATION_UNSPECIFIED_FAILURE);
437 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _, _));
438
439 RunOneStepAndExpect(
440 key_type, /*will_register_key=*/false, kEmptyKeyName,
441 TpmChallengeKeyResult::MakeError(
442 TpmChallengeKeyResultCode::kGetCertificateFailedError));
443 }
444
TEST_F(TpmChallengeKeySubtleTest,KeyExists)445 TEST_F(TpmChallengeKeySubtleTest, KeyExists) {
446 InitSigninProfile();
447 const AttestationKeyType key_type = KEY_DEVICE;
448
449 AttestationClient::Get()
450 ->GetTestInterface()
451 ->GetMutableKeyInfoReply(/*username=*/"", kEnterpriseMachineKey)
452 ->set_public_key(GetPublicKey());
453
454 RunOneStepAndExpect(key_type, /*will_register_key=*/false, kEmptyKeyName,
455 TpmChallengeKeyResult::MakePublicKey(GetPublicKey()));
456 }
457
TEST_F(TpmChallengeKeySubtleTest,AttestationNotPrepared)458 TEST_F(TpmChallengeKeySubtleTest, AttestationNotPrepared) {
459 InitSigninProfile();
460
461 chromeos::AttestationClient::Get()
462 ->GetTestInterface()
463 ->ConfigureEnrollmentPreparations(false);
464
465 RunOneStepAndExpect(KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
466 TpmChallengeKeyResult::MakeError(
467 TpmChallengeKeyResultCode::kResetRequiredError));
468 }
469
470 // Test that we get a proper error message in case we don't have a TPM.
TEST_F(TpmChallengeKeySubtleTest,AttestationUnsupported)471 TEST_F(TpmChallengeKeySubtleTest, AttestationUnsupported) {
472 InitSigninProfile();
473 chromeos::AttestationClient::Get()
474 ->GetTestInterface()
475 ->ConfigureEnrollmentPreparations(false);
476 cryptohome_client_.set_tpm_is_enabled(false);
477
478 RunOneStepAndExpect(
479 KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
480 TpmChallengeKeyResult::MakeError(
481 TpmChallengeKeyResultCode::kAttestationUnsupportedError));
482 }
483
TEST_F(TpmChallengeKeySubtleTest,AttestationPreparedDbusFailed)484 TEST_F(TpmChallengeKeySubtleTest, AttestationPreparedDbusFailed) {
485 InitSigninProfile();
486
487 chromeos::AttestationClient::Get()
488 ->GetTestInterface()
489 ->ConfigureEnrollmentPreparationsStatus(::attestation::STATUS_DBUS_ERROR);
490
491 RunOneStepAndExpect(
492 KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
493 TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError));
494 }
495
TEST_F(TpmChallengeKeySubtleTest,AttestationPreparedServiceInternalError)496 TEST_F(TpmChallengeKeySubtleTest, AttestationPreparedServiceInternalError) {
497 InitSigninProfile();
498
499 chromeos::AttestationClient::Get()
500 ->GetTestInterface()
501 ->ConfigureEnrollmentPreparationsStatus(
502 ::attestation::STATUS_NOT_AVAILABLE);
503
504 RunOneStepAndExpect(
505 KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName,
506 TpmChallengeKeyResult::MakeError(
507 TpmChallengeKeyResultCode::kAttestationServiceInternalError));
508 }
509
TEST_F(TpmChallengeKeySubtleTest,DeviceKeyNotRegisteredSuccess)510 TEST_F(TpmChallengeKeySubtleTest, DeviceKeyNotRegisteredSuccess) {
511 InitSigninProfile();
512 const AttestationKeyType key_type = KEY_DEVICE;
513 const char* const key_name = GetDefaultKeyName(key_type);
514
515 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
516
517 ::attestation::SignEnterpriseChallengeRequest expected_request;
518 expected_request.set_key_label(key_name);
519 expected_request.set_domain(kTestUserDomain);
520 expected_request.set_device_id(GetInstallAttributes()->GetDeviceId());
521 AttestationClient::Get()
522 ->GetTestInterface()
523 ->AllowlistSignEnterpriseChallengeKey(expected_request);
524
525 RunTwoStepsAndExpect(key_type, /*will_register_key=*/false, kEmptyKeyName,
526 TpmChallengeKeyResult::MakeChallengeResponse(
527 GetChallengeResponse(/*include_spkac=*/false)));
528 }
529
TEST_F(TpmChallengeKeySubtleTest,DeviceKeyRegisteredSuccess)530 TEST_F(TpmChallengeKeySubtleTest, DeviceKeyRegisteredSuccess) {
531 InitSigninProfile();
532 const AttestationKeyType key_type = KEY_DEVICE;
533 const char* const key_name = kNonDefaultKeyName;
534
535 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
536
537 ::attestation::SignEnterpriseChallengeRequest expected_request;
538 expected_request.set_key_label(GetDefaultKeyName(key_type));
539 expected_request.set_key_name_for_spkac(key_name);
540 expected_request.set_domain(kTestUserDomain);
541 expected_request.set_device_id(GetInstallAttributes()->GetDeviceId());
542 AttestationClient::Get()
543 ->GetTestInterface()
544 ->AllowlistSignEnterpriseChallengeKey(expected_request);
545
546 AttestationClient::Get()->GetTestInterface()->AllowlistRegisterKey(
547 /*username=*/"", key_name);
548
549 EXPECT_CALL(
550 *system_token_key_permissions_manager_,
551 AllowKeyForUsage(/*callback=*/_, platform_keys::KeyUsage::kCorporate,
552 GetPublicKey()))
553 .WillOnce(RunOnceCallback<0>(platform_keys::Status::kSuccess));
554
555 RunThreeStepsAndExpect(key_type, /*will_register_key=*/true, key_name,
556 TpmChallengeKeyResult::MakeSuccess());
557 }
558
TEST_F(TpmChallengeKeySubtleTest,UserKeyNotRegisteredSuccess)559 TEST_F(TpmChallengeKeySubtleTest, UserKeyNotRegisteredSuccess) {
560 InitAffiliatedProfile();
561
562 const AttestationKeyType key_type = KEY_USER;
563 const char* const key_name = GetDefaultKeyName(key_type);
564
565 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
566
567 ::attestation::SignEnterpriseChallengeRequest expected_request;
568 expected_request.set_username(kTestUserEmail);
569 expected_request.set_key_label(GetDefaultKeyName(key_type));
570 expected_request.set_domain(kTestUserEmail);
571 expected_request.set_device_id(GetInstallAttributes()->GetDeviceId());
572 AttestationClient::Get()
573 ->GetTestInterface()
574 ->AllowlistSignEnterpriseChallengeKey(expected_request);
575
576 RunTwoStepsAndExpect(key_type, /*will_register_key=*/false, kEmptyKeyName,
577 TpmChallengeKeyResult::MakeChallengeResponse(
578 GetChallengeResponse(/*include_spkac=*/false)));
579 }
580
TEST_F(TpmChallengeKeySubtleTest,UserKeyRegisteredSuccess)581 TEST_F(TpmChallengeKeySubtleTest, UserKeyRegisteredSuccess) {
582 InitAffiliatedProfile();
583
584 const AttestationKeyType key_type = KEY_USER;
585 const char* const key_name = kNonDefaultKeyName;
586
587 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
588
589 ::attestation::SignEnterpriseChallengeRequest expected_request;
590 expected_request.set_username(kTestUserEmail);
591 expected_request.set_key_label(kNonDefaultKeyName);
592 expected_request.set_domain(kTestUserEmail);
593 expected_request.set_device_id(GetInstallAttributes()->GetDeviceId());
594 AttestationClient::Get()
595 ->GetTestInterface()
596 ->AllowlistSignEnterpriseChallengeKey(expected_request);
597
598 AttestationClient::Get()->GetTestInterface()->AllowlistRegisterKey(
599 kTestUserEmail, key_name);
600
601 EXPECT_CALL(
602 *user_private_token_key_permissions_manager_,
603 AllowKeyForUsage(/*callback=*/_, platform_keys::KeyUsage::kCorporate,
604 GetPublicKey()))
605 .WillOnce(RunOnceCallback<0>(platform_keys::Status::kSuccess));
606
607 RunThreeStepsAndExpect(key_type, /*will_register_key=*/true, key_name,
608 TpmChallengeKeyResult::MakeSuccess());
609 }
610
TEST_F(TpmChallengeKeySubtleTest,SignChallengeFailed)611 TEST_F(TpmChallengeKeySubtleTest, SignChallengeFailed) {
612 InitSigninProfile();
613 const AttestationKeyType key_type = KEY_DEVICE;
614
615 EXPECT_CALL(mock_attestation_flow_,
616 GetCertificate(_, _, _, _, GetDefaultKeyName(key_type), _));
617
618 // The signing operations fails because we don't allowlist any key.
619 RunTwoStepsAndExpect(
620 key_type, /*will_register_key=*/false, kEmptyKeyName,
621 TpmChallengeKeyResult::MakeError(
622 TpmChallengeKeyResultCode::kSignChallengeFailedError));
623 }
624
TEST_F(TpmChallengeKeySubtleTest,RestorePreparedKeyState)625 TEST_F(TpmChallengeKeySubtleTest, RestorePreparedKeyState) {
626 InitAffiliatedProfile();
627 const AttestationKeyType key_type = KEY_USER;
628 const char* const key_name = kNonDefaultKeyName;
629
630 // Inject mocks into the next result of CreateForPreparedKey.
631 TpmChallengeKeySubtleFactory::SetForTesting(
632 std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_,
633 &mock_cert_uploader_));
634
635 challenge_key_subtle_ = TpmChallengeKeySubtleFactory::CreateForPreparedKey(
636 key_type, /*will_register_key=*/true, key_name, GetPublicKey(),
637 GetProfile());
638
639 ::attestation::SignEnterpriseChallengeRequest expected_request;
640 expected_request.set_username(kTestUserEmail);
641 expected_request.set_key_label(kNonDefaultKeyName);
642 expected_request.set_domain(kTestUserEmail);
643 expected_request.set_device_id(GetInstallAttributes()->GetDeviceId());
644 AttestationClient::Get()
645 ->GetTestInterface()
646 ->AllowlistSignEnterpriseChallengeKey(expected_request);
647
648 {
649 CallbackObserver callback_observer;
650 challenge_key_subtle_->StartSignChallengeStep(
651 GetChallenge(), callback_observer.GetCallback());
652 callback_observer.WaitForCallback();
653
654 EXPECT_EQ(callback_observer.GetResult(),
655 TpmChallengeKeyResult::MakeChallengeResponse(
656 GetChallengeResponse(/*include_spkac=*/true)));
657 }
658
659 AttestationClient::Get()->GetTestInterface()->AllowlistRegisterKey(
660 kTestUserEmail, key_name);
661
662 EXPECT_CALL(
663 *user_private_token_key_permissions_manager_,
664 AllowKeyForUsage(/*callback=*/_, platform_keys::KeyUsage::kCorporate,
665 GetPublicKey()))
666 .WillOnce(RunOnceCallback<0>(platform_keys::Status::kSuccess));
667
668 {
669 CallbackObserver callback_observer;
670 challenge_key_subtle_->StartRegisterKeyStep(
671 callback_observer.GetCallback());
672 callback_observer.WaitForCallback();
673
674 EXPECT_EQ(callback_observer.GetResult(),
675 TpmChallengeKeyResult::MakeSuccess());
676 }
677 }
678
TEST_F(TpmChallengeKeySubtleTest,KeyRegistrationFailed)679 TEST_F(TpmChallengeKeySubtleTest, KeyRegistrationFailed) {
680 InitAffiliatedProfile();
681 const AttestationKeyType key_type = KEY_USER;
682 const char* const key_name = kNonDefaultKeyName;
683
684 // Inject mocks into the next result of CreateForPreparedKey.
685 TpmChallengeKeySubtleFactory::SetForTesting(
686 std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_,
687 &mock_cert_uploader_));
688
689 challenge_key_subtle_ = TpmChallengeKeySubtleFactory::CreateForPreparedKey(
690 key_type, /*will_register_key=*/true, key_name, GetPublicKey(),
691 GetProfile());
692
693 CallbackObserver callback_observer;
694 challenge_key_subtle_->StartRegisterKeyStep(callback_observer.GetCallback());
695 callback_observer.WaitForCallback();
696
697 EXPECT_EQ(callback_observer.GetResult(),
698 TpmChallengeKeyResult::MakeError(
699 TpmChallengeKeyResultCode::kKeyRegistrationFailedError));
700 }
701
TEST_F(TpmChallengeKeySubtleTest,GetPublicKeyFailed)702 TEST_F(TpmChallengeKeySubtleTest, GetPublicKeyFailed) {
703 InitAffiliatedProfile();
704 const char* const key_name = kNonDefaultKeyName;
705
706 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
707
708 // Force the attestation client to report absence even after successful
709 // attestation flow.
710 AttestationClient::Get()
711 ->GetTestInterface()
712 ->GetMutableKeyInfoReply(/*username=*/"", key_name)
713 ->set_status(::attestation::STATUS_INVALID_PARAMETER);
714
715 RunOneStepAndExpect(KEY_DEVICE, /*will_register_key=*/true, key_name,
716 TpmChallengeKeyResult::MakeError(
717 TpmChallengeKeyResultCode::kGetPublicKeyFailedError));
718 }
719
TEST_F(TpmChallengeKeySubtleTest,WaitForCertificateUploaded)720 TEST_F(TpmChallengeKeySubtleTest, WaitForCertificateUploaded) {
721 InitAffiliatedProfile();
722 const char* const key_name = kNonDefaultKeyName;
723
724 using CallbackHolderT =
725 CallbackHolder<MachineCertificateUploader::UploadCallback>;
726 CallbackHolderT callback_holder;
727 EXPECT_CALL(mock_cert_uploader_, WaitForUploadComplete)
728 .WillOnce(
729 testing::Invoke(&callback_holder, &CallbackHolderT::SaveCallback));
730
731 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
732
733 CallbackObserver callback_observer;
734 challenge_key_subtle_->StartPrepareKeyStep(
735 KEY_DEVICE, /*will_register_key=*/true, key_name, GetProfile(),
736 callback_observer.GetCallback());
737
738 // |challenge_key_subtle_| should wait until the certificate is uploaded.
739 task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10));
740 EXPECT_FALSE(callback_observer.IsResultReceived());
741
742 // Emulate callback from the certificate uploader, |challenge_key_subtle_|
743 // should be able to continue now.
744 std::move(callback_holder.callback).Run(true);
745 callback_observer.WaitForCallback();
746
747 EXPECT_EQ(callback_observer.GetResult(),
748 TpmChallengeKeyResult::MakePublicKey(GetPublicKey()));
749 }
750
751 // Check that the class works when MachineCertificateUploader is not provided
752 // (e.g. if device is managed by Active Directory).
TEST_F(TpmChallengeKeySubtleTest,NoCertificateUploaderSuccess)753 TEST_F(TpmChallengeKeySubtleTest, NoCertificateUploaderSuccess) {
754 InitAffiliatedProfile();
755 const char* const key_name = kNonDefaultKeyName;
756
757 challenge_key_subtle_ = std::make_unique<TpmChallengeKeySubtleImpl>(
758 &mock_attestation_flow_, /*machine_certificate_uploader=*/nullptr);
759
760 EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _));
761
762 RunOneStepAndExpect(KEY_USER, /*will_register_key=*/true, key_name,
763 TpmChallengeKeyResult::MakePublicKey(GetPublicKey()));
764 }
765
766 } // namespace
767 } // namespace attestation
768 } // namespace chromeos
769