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