| // Copyright 2020 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/ash/attestation/tpm_challenge_key_subtle.h" | 
 |  | 
 | #include <stdint.h> | 
 |  | 
 | #include <optional> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "base/functional/bind.h" | 
 | #include "base/memory/raw_ptr.h" | 
 | #include "base/run_loop.h" | 
 | #include "base/test/gmock_callback_support.h" | 
 | #include "base/time/time.h" | 
 | #include "chrome/browser/ash/attestation/mock_machine_certificate_uploader.h" | 
 | #include "chrome/browser/ash/attestation/tpm_challenge_key_result.h" | 
 | #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" | 
 | #include "chrome/browser/ash/platform_keys/key_permissions/fake_user_private_token_kpm_service.h" | 
 | #include "chrome/browser/ash/platform_keys/key_permissions/key_permissions_manager_impl.h" | 
 | #include "chrome/browser/ash/platform_keys/key_permissions/mock_key_permissions_manager.h" | 
 | #include "chrome/browser/ash/platform_keys/key_permissions/user_private_token_kpm_service_factory.h" | 
 | #include "chrome/browser/chromeos/platform_keys/platform_keys.h" | 
 | #include "chrome/browser/policy/profile_policy_connector.h" | 
 | #include "chrome/common/chrome_constants.h" | 
 | #include "chrome/common/pref_names.h" | 
 | #include "chrome/test/base/testing_browser_process.h" | 
 | #include "chrome/test/base/testing_profile.h" | 
 | #include "chrome/test/base/testing_profile_manager.h" | 
 | #include "chromeos/ash/components/attestation/mock_attestation_flow.h" | 
 | #include "chromeos/ash/components/cryptohome/cryptohome_parameters.h" | 
 | #include "chromeos/ash/components/dbus/attestation/fake_attestation_client.h" | 
 | #include "chromeos/ash/components/dbus/attestation/interface.pb.h" | 
 | #include "chromeos/ash/components/dbus/constants/attestation_constants.h" | 
 | #include "chromeos/components/kiosk/kiosk_test_utils.h" | 
 | #include "chromeos/dbus/tpm_manager/tpm_manager_client.h" | 
 | #include "components/prefs/pref_service.h" | 
 | #include "components/sync_preferences/testing_pref_service_syncable.h" | 
 | #include "components/user_manager/scoped_user_manager.h" | 
 | #include "content/public/test/browser_task_environment.h" | 
 | #include "google_apis/gaia/gaia_auth_util.h" | 
 | #include "testing/gtest/include/gtest/gtest.h" | 
 |  | 
 | using base::test::RunOnceCallback; | 
 | using testing::_; | 
 | using testing::Invoke; | 
 | using testing::StrictMock; | 
 |  | 
 | namespace ash { | 
 | namespace attestation { | 
 | namespace { | 
 |  | 
 | constexpr char kTestUserEmail[] = "test@google.com"; | 
 | constexpr char kTestUserGaiaId[] = "test_gaia_id"; | 
 | constexpr char kEmptyKeyName[] = ""; | 
 | constexpr char kNonDefaultKeyName[] = "key_name_123"; | 
 | constexpr char kFakeCertificate[] = "fake_cert"; | 
 | constexpr char kUnsupportedVAFlowTypeKey[] = "unsupported VA flow type"; | 
 |  | 
 | std::string GetDefaultKeyName(::attestation::VerifiedAccessFlow type, | 
 |                               const std::string& username = std::string()) { | 
 |   switch (type) { | 
 |     case ::attestation::ENTERPRISE_MACHINE: | 
 |       return kEnterpriseMachineKey; | 
 |     case ::attestation::ENTERPRISE_USER: | 
 |       return kEnterpriseUserKey; | 
 |     default: | 
 |       return kUnsupportedVAFlowTypeKey; | 
 |   } | 
 | } | 
 |  | 
 | std::string GetChallenge() { | 
 |   constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2,  'c',  'h', | 
 |                                  'a', 'l', 0xfd, 0xfe, 0xff}; | 
 |   return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); | 
 | } | 
 |  | 
 | std::string GetChallengeResponse(bool include_spkac) { | 
 |   return AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->GetEnterpriseChallengeFakeSignature(GetChallenge(), include_spkac); | 
 | } | 
 |  | 
 | std::string GetPublicKey() { | 
 |   constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2,  'p',  'u', | 
 |                                  'b', 'k', 0xfd, 0xfe, 0xff}; | 
 |   return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); | 
 | } | 
 |  | 
 | std::vector<uint8_t> GetPublicKeyBin() { | 
 |   constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2,  'p',  'u', | 
 |                                  'b', 'k', 0xfd, 0xfe, 0xff}; | 
 |   return std::vector<uint8_t>(std::begin(kBuffer), std::end(kBuffer)); | 
 | } | 
 |  | 
 | class CallbackObserver { | 
 |  public: | 
 |   TpmChallengeKeyCallback GetCallback() { | 
 |     return base::BindOnce(&CallbackObserver::Callback, base::Unretained(this)); | 
 |   } | 
 |  | 
 |   bool IsResultReceived() const { return result_.has_value(); } | 
 |  | 
 |   const TpmChallengeKeyResult& GetResult() const { | 
 |     CHECK(result_.has_value()) << "Callback was never called"; | 
 |     return result_.value(); | 
 |   } | 
 |  | 
 |   void WaitForCallback() { loop_.Run(); } | 
 |  | 
 |  private: | 
 |   void Callback(const TpmChallengeKeyResult& result) { | 
 |     CHECK(!result_.has_value()) << "Callback was called more than once"; | 
 |     result_ = result; | 
 |     loop_.Quit(); | 
 |   } | 
 |  | 
 |   base::RunLoop loop_; | 
 |   std::optional<TpmChallengeKeyResult> result_; | 
 | }; | 
 |  | 
 | template <typename T> | 
 | struct CallbackHolder { | 
 |   void SaveCallback(T new_callback) { | 
 |     CHECK(callback.is_null()); | 
 |     callback = std::move(new_callback); | 
 |   } | 
 |  | 
 |   T callback; | 
 | }; | 
 |  | 
 | //================= MockableFakeAttestationFlow ================================ | 
 |  | 
 | class MockableFakeAttestationFlow : public MockAttestationFlow { | 
 |  public: | 
 |   MockableFakeAttestationFlow() { | 
 |     ON_CALL(*this, GetCertificate(_, _, _, _, _, _, _, _)) | 
 |         .WillByDefault( | 
 |             Invoke(this, &MockableFakeAttestationFlow::GetCertificateInternal)); | 
 |   } | 
 |   ~MockableFakeAttestationFlow() override = default; | 
 |   void set_status(AttestationStatus status) { status_ = status; } | 
 |  | 
 |  private: | 
 |   void GetCertificateInternal( | 
 |       AttestationCertificateProfile /*certificate_profile*/, | 
 |       const AccountId& account_id, | 
 |       const std::string& /*request_origin*/, | 
 |       bool /*force_new_key*/, | 
 |       ::attestation::KeyType /*key_crypto_type*/, | 
 |       const std::string& key_name, | 
 |       const std::optional<AttestationFlow::CertProfileSpecificData>& | 
 |           profile_specific_data, | 
 |       CertificateCallback callback) { | 
 |     std::string certificate; | 
 |     if (status_ == ATTESTATION_SUCCESS) { | 
 |       certificate = certificate_; | 
 |       AttestationClient::Get() | 
 |           ->GetTestInterface() | 
 |           ->GetMutableKeyInfoReply(cryptohome::Identification(account_id).id(), | 
 |                                    key_name) | 
 |           ->set_public_key(public_key_); | 
 |     } | 
 |     std::move(callback).Run(status_, certificate); | 
 |   } | 
 |   AttestationStatus status_ = ATTESTATION_SUCCESS; | 
 |   const std::string certificate_ = kFakeCertificate; | 
 |   const std::string public_key_ = GetPublicKey(); | 
 | }; | 
 |  | 
 | //==================== TpmChallengeKeySubtleTestBase =========================== | 
 |  | 
 | // Describes which kind of profile will be used with TpmChallengeKeySubtle. | 
 | enum class TestProfileChoice { | 
 |   // Pass nullptr as Profile. | 
 |   kNoProfile, | 
 |   // Pass the sign-in Profile. | 
 |   kSigninProfile, | 
 |   // Pass the Profile of an unmanaged user. | 
 |   kUnmanagedProfile, | 
 |   // Pass the Profile of a managed, unaffiliated user. | 
 |   kUnaffiliatedProfile, | 
 |   // Pass the Profile of an affiliated user. | 
 |   kAffiliatedProfile, | 
 |   // Pass the Profile of signed-in kiosk user. | 
 |   kKioskProfile | 
 | }; | 
 |  | 
 | class TpmChallengeKeySubtleTestBase : public ::testing::Test { | 
 |  public: | 
 |   explicit TpmChallengeKeySubtleTestBase(TestProfileChoice test_profile_choice); | 
 |   ~TpmChallengeKeySubtleTestBase() override; | 
 |  | 
 |  protected: | 
 |   // ::testing::Test: | 
 |   void SetUp() override; | 
 |  | 
 |   TestingProfile* CreateUserProfile(bool is_managed, bool is_affiliated); | 
 |   virtual TestingProfile* CreateKioskProfile(); | 
 |   TestingProfile* GetProfile(); | 
 |   ScopedCrosSettingsTestHelper* GetCrosSettingsHelper(); | 
 |   StubInstallAttributes* GetInstallAttributes(); | 
 |   std::string GetTestingProfileDomainName(); | 
 |  | 
 |   // Runs StartPrepareKeyStep and checks that the result is equal to | 
 |   // |public_key|. | 
 |   void RunOneStepAndExpect(::attestation::VerifiedAccessFlow flow_type, | 
 |                            bool will_register_key, | 
 |                            const std::string& key_name, | 
 |                            const TpmChallengeKeyResult& public_key); | 
 |   // Runs StartPrepareKeyStep and checks that the result is success. Then runs | 
 |   // StartSignChallengeStep and checks that the result is equal to | 
 |   // |challenge_response|. | 
 |   void RunTwoStepsAndExpect(::attestation::VerifiedAccessFlow flow_type, | 
 |                             bool will_register_key, | 
 |                             const std::string& key_name, | 
 |                             const TpmChallengeKeyResult& challenge_response); | 
 |   // Runs first two steps and checks that results are success. Then runs | 
 |   // StartRegisterKeyStep and checks that the result is equal to | 
 |   // |register_result|. | 
 |   void RunThreeStepsAndExpect(::attestation::VerifiedAccessFlow flow_type, | 
 |                               bool will_register_key, | 
 |                               const std::string& key_name, | 
 |                               const TpmChallengeKeyResult& register_result); | 
 |  | 
 |   virtual ::attestation::KeyType KeyCryptoType(); | 
 |  | 
 |  protected: | 
 |   const TestProfileChoice test_profile_choice_; | 
 |  | 
 |   content::BrowserTaskEnvironment task_environment_{ | 
 |       base::test::TaskEnvironment::TimeSource::MOCK_TIME}; | 
 |  | 
 |   StrictMock<MockableFakeAttestationFlow> mock_attestation_flow_; | 
 |   std::unique_ptr<platform_keys::MockKeyPermissionsManager> | 
 |       system_token_key_permissions_manager_; | 
 |   std::unique_ptr<platform_keys::MockKeyPermissionsManager> | 
 |       user_private_token_key_permissions_manager_; | 
 |   MockMachineCertificateUploader mock_cert_uploader_; | 
 |  | 
 |   std::unique_ptr<TpmChallengeKeySubtle> challenge_key_subtle_; | 
 |  | 
 |   TestingProfileManager testing_profile_manager_; | 
 |   user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> | 
 |       fake_user_manager_{std::make_unique<ash::FakeChromeUserManager>()}; | 
 |   // A sign-in Profile is always created in SetUp(). | 
 |   raw_ptr<TestingProfile> signin_profile_ = nullptr; | 
 |   // The profile that will be passed to TpmChallengeKeySubtle - can be nullptr. | 
 |   raw_ptr<TestingProfile> testing_profile_ = nullptr; | 
 | }; | 
 |  | 
 | TpmChallengeKeySubtleTestBase::TpmChallengeKeySubtleTestBase( | 
 |     TestProfileChoice test_profile_choice) | 
 |     : test_profile_choice_(test_profile_choice), | 
 |       testing_profile_manager_(TestingBrowserProcess::GetGlobal()) { | 
 |   ::chromeos::TpmManagerClient::InitializeFake(); | 
 |   AttestationClient::InitializeFake(); | 
 |   CHECK(testing_profile_manager_.SetUp()); | 
 |  | 
 |   challenge_key_subtle_ = std::make_unique<TpmChallengeKeySubtleImpl>( | 
 |       &mock_attestation_flow_, &mock_cert_uploader_); | 
 |  | 
 |   // By default make it reply that the certificate is already uploaded. | 
 |   ON_CALL(mock_cert_uploader_, WaitForUploadComplete) | 
 |       .WillByDefault(base::test::RunOnceCallbackRepeatedly<0>(true)); | 
 | } | 
 |  | 
 | TpmChallengeKeySubtleTestBase::~TpmChallengeKeySubtleTestBase() { | 
 |   AttestationClient::Shutdown(); | 
 |   ::chromeos::TpmManagerClient::Shutdown(); | 
 | } | 
 |  | 
 | void TpmChallengeKeySubtleTestBase::SetUp() { | 
 |   signin_profile_ = | 
 |       testing_profile_manager_.CreateTestingProfile(chrome::kInitialProfile); | 
 |   switch (test_profile_choice_) { | 
 |     case TestProfileChoice::kNoProfile: | 
 |       testing_profile_ = nullptr; | 
 |       break; | 
 |     case TestProfileChoice::kSigninProfile: | 
 |       testing_profile_ = signin_profile_; | 
 |       break; | 
 |     case TestProfileChoice::kUnmanagedProfile: | 
 |       testing_profile_ = | 
 |           CreateUserProfile(/*is_managed=*/false, /*is_affiliated=*/false); | 
 |       break; | 
 |     case TestProfileChoice::kUnaffiliatedProfile: | 
 |       testing_profile_ = | 
 |           CreateUserProfile(/*is_managed=*/true, /*is_affiliated=*/false); | 
 |       break; | 
 |     case TestProfileChoice::kAffiliatedProfile: | 
 |       testing_profile_ = | 
 |           CreateUserProfile(/*is_managed=*/true, /*is_affiliated=*/true); | 
 |       break; | 
 |     case TestProfileChoice::kKioskProfile: | 
 |       testing_profile_ = CreateKioskProfile(); | 
 |       break; | 
 |   } | 
 |  | 
 |   GetInstallAttributes()->SetCloudManaged(GetTestingProfileDomainName(), | 
 |                                           "device_id"); | 
 |  | 
 |   system_token_key_permissions_manager_ = | 
 |       std::make_unique<platform_keys::MockKeyPermissionsManager>(); | 
 |   platform_keys::KeyPermissionsManagerImpl:: | 
 |       SetSystemTokenKeyPermissionsManagerForTesting( | 
 |           system_token_key_permissions_manager_.get()); | 
 |  | 
 |   if (!testing_profile_) { | 
 |     return; | 
 |   } | 
 |   user_private_token_key_permissions_manager_ = | 
 |       std::make_unique<platform_keys::MockKeyPermissionsManager>(); | 
 |   platform_keys::UserPrivateTokenKeyPermissionsManagerServiceFactory:: | 
 |       GetInstance() | 
 |           ->SetTestingFactory( | 
 |               testing_profile_, | 
 |               base::BindRepeating( | 
 |                   &platform_keys:: | 
 |                       BuildFakeUserPrivateTokenKeyPermissionsManagerService, | 
 |                   user_private_token_key_permissions_manager_.get())); | 
 | } | 
 |  | 
 | TestingProfile* TpmChallengeKeySubtleTestBase::CreateUserProfile( | 
 |     bool is_managed, | 
 |     bool is_affiliated) { | 
 |   TestingProfile* testing_profile = | 
 |       testing_profile_manager_.CreateTestingProfile(kTestUserEmail); | 
 |   CHECK(testing_profile); | 
 |  | 
 |   testing_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting( | 
 |       is_managed); | 
 |  | 
 |   auto test_account = | 
 |       AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); | 
 |   fake_user_manager_->AddUserWithAffiliation(test_account, is_affiliated); | 
 |  | 
 |   return testing_profile; | 
 | } | 
 |  | 
 | TestingProfile* TpmChallengeKeySubtleTestBase::CreateKioskProfile() { | 
 |   return nullptr; | 
 | } | 
 |  | 
 | TestingProfile* TpmChallengeKeySubtleTestBase::GetProfile() { | 
 |   return testing_profile_; | 
 | } | 
 |  | 
 | ScopedCrosSettingsTestHelper* | 
 | TpmChallengeKeySubtleTestBase::GetCrosSettingsHelper() { | 
 |   return signin_profile_->ScopedCrosSettingsTestHelper(); | 
 | } | 
 |  | 
 | StubInstallAttributes* TpmChallengeKeySubtleTestBase::GetInstallAttributes() { | 
 |   return GetCrosSettingsHelper()->InstallAttributes(); | 
 | } | 
 |  | 
 | std::string TpmChallengeKeySubtleTestBase::GetTestingProfileDomainName() { | 
 |   if (!testing_profile_ || testing_profile_ == signin_profile_) { | 
 |     // Fallback to the constant domain if there is no `testing_profile_` or | 
 |     // a default `signin_profile_` only. | 
 |     return "fake.domain"; | 
 |   } | 
 |   return gaia::ExtractDomainName(testing_profile_->GetProfileUserName()); | 
 | } | 
 |  | 
 | ::attestation::KeyType TpmChallengeKeySubtleTestBase::KeyCryptoType() { | 
 |   return ::attestation::KEY_TYPE_RSA; | 
 | } | 
 |  | 
 | void TpmChallengeKeySubtleTestBase::RunOneStepAndExpect( | 
 |     ::attestation::VerifiedAccessFlow flow_type, | 
 |     bool will_register_key, | 
 |     const std::string& key_name, | 
 |     const TpmChallengeKeyResult& public_key) { | 
 |   CallbackObserver callback_observer; | 
 |   challenge_key_subtle_->StartPrepareKeyStep( | 
 |       flow_type, will_register_key, KeyCryptoType(), key_name, GetProfile(), | 
 |       callback_observer.GetCallback(), /*signals=*/std::nullopt); | 
 |   callback_observer.WaitForCallback(); | 
 |  | 
 |   EXPECT_EQ(callback_observer.GetResult(), public_key); | 
 | } | 
 |  | 
 | void TpmChallengeKeySubtleTestBase::RunTwoStepsAndExpect( | 
 |     ::attestation::VerifiedAccessFlow flow_type, | 
 |     bool will_register_key, | 
 |     const std::string& key_name, | 
 |     const TpmChallengeKeyResult& challenge_response) { | 
 |   RunOneStepAndExpect(flow_type, will_register_key, key_name, | 
 |                       TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 |  | 
 |   CallbackObserver callback_observer; | 
 |   challenge_key_subtle_->StartSignChallengeStep( | 
 |       GetChallenge(), callback_observer.GetCallback()); | 
 |   callback_observer.WaitForCallback(); | 
 |  | 
 |   EXPECT_EQ(callback_observer.GetResult(), challenge_response); | 
 | } | 
 |  | 
 | void TpmChallengeKeySubtleTestBase::RunThreeStepsAndExpect( | 
 |     ::attestation::VerifiedAccessFlow flow_type, | 
 |     bool will_register_key, | 
 |     const std::string& key_name, | 
 |     const TpmChallengeKeyResult& register_result) { | 
 |   RunTwoStepsAndExpect(flow_type, will_register_key, key_name, | 
 |                        TpmChallengeKeyResult::MakeChallengeResponse( | 
 |                            GetChallengeResponse(will_register_key))); | 
 |  | 
 |   CallbackObserver callback_observer; | 
 |   challenge_key_subtle_->StartRegisterKeyStep(callback_observer.GetCallback()); | 
 |   callback_observer.WaitForCallback(); | 
 |  | 
 |   EXPECT_EQ(callback_observer.GetResult(), register_result); | 
 | } | 
 |  | 
 | //============================================================================== | 
 |  | 
 | // Tests all Profile* options where TpmChallengeKeySubtle can be used with | 
 | // device-wide keys, including passing profile=nullptr. | 
 | class DeviceKeysAccessTpmChallengeKeySubtleTest | 
 |     : public TpmChallengeKeySubtleTestBase, | 
 |       public ::testing::WithParamInterface<TestProfileChoice> { | 
 |  public: | 
 |   DeviceKeysAccessTpmChallengeKeySubtleTest() | 
 |       : TpmChallengeKeySubtleTestBase(GetParam()) {} | 
 |   ~DeviceKeysAccessTpmChallengeKeySubtleTest() = default; | 
 | }; | 
 |  | 
 | INSTANTIATE_TEST_SUITE_P( | 
 |     DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |     DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |     testing::Values(TestProfileChoice::kNoProfile, | 
 |                     TestProfileChoice::kSigninProfile, | 
 |                     TestProfileChoice::kAffiliatedProfile)); | 
 |  | 
 | // Tests TpmChallengeKeySubtle with the sign-in Profile only. | 
 | class SigninProfileTpmChallengeKeySubtleTest | 
 |     : public TpmChallengeKeySubtleTestBase { | 
 |  public: | 
 |   SigninProfileTpmChallengeKeySubtleTest() | 
 |       : TpmChallengeKeySubtleTestBase(TestProfileChoice::kSigninProfile) {} | 
 |   ~SigninProfileTpmChallengeKeySubtleTest() override = default; | 
 | }; | 
 |  | 
 | // Tests TpmChallengeKeySubtle with an affiliated user profile only. | 
 | class AffiliatedUserTpmChallengeKeySubtleTest | 
 |     : public TpmChallengeKeySubtleTestBase { | 
 |  public: | 
 |   AffiliatedUserTpmChallengeKeySubtleTest() | 
 |       : TpmChallengeKeySubtleTestBase(TestProfileChoice::kAffiliatedProfile) {} | 
 |   ~AffiliatedUserTpmChallengeKeySubtleTest() override = default; | 
 | }; | 
 |  | 
 | // Tests TpmChallengeKeySubtle with an unmanaged user profile only. | 
 | class UnmanagedUserTpmChallengeKeySubtleTest | 
 |     : public TpmChallengeKeySubtleTestBase { | 
 |  public: | 
 |   UnmanagedUserTpmChallengeKeySubtleTest() | 
 |       : TpmChallengeKeySubtleTestBase(TestProfileChoice::kUnmanagedProfile) {} | 
 |   ~UnmanagedUserTpmChallengeKeySubtleTest() override = default; | 
 | }; | 
 |  | 
 | // Tests TpmChallengeKeySubtle with a managed, unaffiliated user profile only. | 
 | class UnaffiliatedUserTpmChallengeKeySubtleTest | 
 |     : public TpmChallengeKeySubtleTestBase { | 
 |  public: | 
 |   UnaffiliatedUserTpmChallengeKeySubtleTest() | 
 |       : TpmChallengeKeySubtleTestBase(TestProfileChoice::kUnaffiliatedProfile) { | 
 |   } | 
 |   ~UnaffiliatedUserTpmChallengeKeySubtleTest() override = default; | 
 | }; | 
 |  | 
 | // Tests TpmChallengeKeySubtle in a kiosk session. | 
 | class KioskTpmChallengeKeySubtleTest : public TpmChallengeKeySubtleTestBase { | 
 |  public: | 
 |   KioskTpmChallengeKeySubtleTest() | 
 |       : TpmChallengeKeySubtleTestBase(TestProfileChoice::kKioskProfile) {} | 
 |   ~KioskTpmChallengeKeySubtleTest() override = default; | 
 |  | 
 |   TestingProfile* CreateKioskProfile() override { | 
 |     chromeos::SetUpFakeKioskSession(); | 
 |     auto* user = fake_user_manager_->GetActiveUser(); | 
 |     kiosk_user_email_ = user->GetAccountId().GetUserEmail(); | 
 |     auto* testing_profile = | 
 |         testing_profile_manager_.CreateTestingProfile(kiosk_user_email_); | 
 |     testing_profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting( | 
 |         true); | 
 |     fake_user_manager_->AddUserWithAffiliation(user->GetAccountId(), | 
 |                                                /* is_affiliated= */ true); | 
 |     return testing_profile; | 
 |   } | 
 |  | 
 |   const std::string& kiosk_user_email() const { return kiosk_user_email_; } | 
 |  | 
 |  private: | 
 |   std::string kiosk_user_email_; | 
 | }; | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |        UnsupportedVerifiedAccessFlow) { | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::CBCM, /*will_register_key=*/false, kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kVerifiedAccessFlowUnsupportedError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |        DeviceKeyNonEnterpriseDevice) { | 
 |   GetInstallAttributes()->SetConsumerOwned(); | 
 |  | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::ENTERPRISE_MACHINE, /*will_register_key=*/false, | 
 |       kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kNonEnterpriseDeviceError)); | 
 | } | 
 |  | 
 | TEST_F(UnaffiliatedUserTpmChallengeKeySubtleTest, DeviceKeyUserNotManaged) { | 
 |   RunOneStepAndExpect(::attestation::ENTERPRISE_MACHINE, | 
 |                       /*will_register_key=*/false, kEmptyKeyName, | 
 |                       TpmChallengeKeyResult::MakeError( | 
 |                           TpmChallengeKeyResultCode::kUserNotManagedError)); | 
 | } | 
 |  | 
 | TEST_F(SigninProfileTpmChallengeKeySubtleTest, UserKeyUserKeyNotAvailable) { | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::ENTERPRISE_USER, /*will_register_key=*/false, | 
 |       kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kUserKeyNotAvailableError)); | 
 | } | 
 |  | 
 | // Checks that a user should be affiliated with a device | 
 | TEST_F(UnaffiliatedUserTpmChallengeKeySubtleTest, UserKeyUserNotAffiliated) { | 
 |   RunOneStepAndExpect(::attestation::ENTERPRISE_USER, | 
 |                       /*will_register_key=*/false, kEmptyKeyName, | 
 |                       TpmChallengeKeyResult::MakeError( | 
 |                           TpmChallengeKeyResultCode::kUserNotManagedError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, DoesKeyExistDbusFailed) { | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->GetMutableKeyInfoReply(/*username=*/"", kEnterpriseMachineKey) | 
 |       ->set_status(::attestation::STATUS_DBUS_ERROR); | 
 |  | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::ENTERPRISE_MACHINE, /*will_register_key=*/false, | 
 |       kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, GetCertificateFailed) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_MACHINE; | 
 |  | 
 |   mock_attestation_flow_.set_status(ATTESTATION_UNSPECIFIED_FAILURE); | 
 |   EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _, _, _, _)); | 
 |  | 
 |   RunOneStepAndExpect( | 
 |       flow_type, /*will_register_key=*/false, kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kGetCertificateFailedError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, KeyExists) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_MACHINE; | 
 |  | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->GetMutableKeyInfoReply(/*username=*/"", kEnterpriseMachineKey) | 
 |       ->set_public_key(GetPublicKey()); | 
 |  | 
 |   RunOneStepAndExpect(flow_type, /*will_register_key=*/false, kEmptyKeyName, | 
 |                       TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, AttestationNotPrepared) { | 
 |   AttestationClient::Get()->GetTestInterface()->ConfigureEnrollmentPreparations( | 
 |       false); | 
 |  | 
 |   RunOneStepAndExpect(::attestation::ENTERPRISE_MACHINE, | 
 |                       /*will_register_key=*/false, kEmptyKeyName, | 
 |                       TpmChallengeKeyResult::MakeError( | 
 |                           TpmChallengeKeyResultCode::kResetRequiredError)); | 
 | } | 
 |  | 
 | // Test that we get a proper error message in case we don't have a TPM. | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, AttestationUnsupported) { | 
 |   AttestationClient::Get()->GetTestInterface()->ConfigureEnrollmentPreparations( | 
 |       false); | 
 |   chromeos::TpmManagerClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->mutable_nonsensitive_status_reply() | 
 |       ->set_is_enabled(false); | 
 |  | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::ENTERPRISE_MACHINE, /*will_register_key=*/false, | 
 |       kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kAttestationUnsupportedError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |        AttestationPreparedDbusFailed) { | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->ConfigureEnrollmentPreparationsStatus(::attestation::STATUS_DBUS_ERROR); | 
 |  | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::ENTERPRISE_MACHINE, /*will_register_key=*/false, | 
 |       kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |        AttestationPreparedServiceInternalError) { | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->ConfigureEnrollmentPreparationsStatus( | 
 |           ::attestation::STATUS_NOT_AVAILABLE); | 
 |  | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::ENTERPRISE_MACHINE, /*will_register_key=*/false, | 
 |       kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kAttestationServiceInternalError)); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, | 
 |        DeviceKeyNotRegisteredSuccess) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_MACHINE; | 
 |   const std::string key_name = GetDefaultKeyName(flow_type); | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_key_label(key_name); | 
 |   expected_request.set_domain(std::string()); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(true); | 
 |   expected_request.set_flow_type(::attestation::ENTERPRISE_MACHINE); | 
 |   expected_request.set_include_certificate(false); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   RunTwoStepsAndExpect(flow_type, /*will_register_key=*/false, kEmptyKeyName, | 
 |                        TpmChallengeKeyResult::MakeChallengeResponse( | 
 |                            GetChallengeResponse(/*include_spkac=*/false))); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, DeviceKeyRegisteredSuccess) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_MACHINE; | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   EXPECT_CALL( | 
 |       mock_attestation_flow_, | 
 |       GetCertificate(_, _, _, _, ::attestation::KEY_TYPE_RSA, key_name, _, _)); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_key_label(GetDefaultKeyName(flow_type)); | 
 |   expected_request.set_key_name_for_spkac(key_name); | 
 |   expected_request.set_domain(std::string()); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(true); | 
 |   expected_request.set_flow_type(::attestation::ENTERPRISE_MACHINE); | 
 |   expected_request.set_include_certificate(false); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   AttestationClient::Get()->GetTestInterface()->AllowlistRegisterKey( | 
 |       /*username=*/"", key_name); | 
 |  | 
 |   EXPECT_CALL( | 
 |       *system_token_key_permissions_manager_, | 
 |       AllowKeyForUsage(/*callback=*/_, platform_keys::KeyUsage::kCorporate, | 
 |                        GetPublicKeyBin())) | 
 |       .WillOnce(RunOnceCallback<0>(chromeos::platform_keys::Status::kSuccess)); | 
 |  | 
 |   RunThreeStepsAndExpect(flow_type, /*will_register_key=*/true, key_name, | 
 |                          TpmChallengeKeyResult::MakeSuccess()); | 
 | } | 
 |  | 
 | class TpmChallengeKeySubtleTestECC : public TpmChallengeKeySubtleTestBase { | 
 |  public: | 
 |   TpmChallengeKeySubtleTestECC() | 
 |       : TpmChallengeKeySubtleTestBase(TestProfileChoice::kAffiliatedProfile) {} | 
 |   ~TpmChallengeKeySubtleTestECC() override = default; | 
 |  | 
 |   // TpmChallengeKeySubtleTestBase | 
 |   ::attestation::KeyType KeyCryptoType() override { | 
 |     return ::attestation::KEY_TYPE_ECC; | 
 |   } | 
 | }; | 
 |  | 
 | TEST_F(TpmChallengeKeySubtleTestECC, DeviceKeyRegisteredSuccessECC) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_MACHINE; | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   EXPECT_CALL( | 
 |       mock_attestation_flow_, | 
 |       GetCertificate(_, _, _, _, ::attestation::KEY_TYPE_ECC, key_name, _, _)); | 
 |  | 
 |   RunOneStepAndExpect(flow_type, /*will_register_key=*/true, key_name, | 
 |                       TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, | 
 |        UserKeyRegisteredSuccessDefaultNameRsa) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const std::string key_name = std::string(kEnterpriseUserKey); | 
 |  | 
 |   EXPECT_CALL( | 
 |       mock_attestation_flow_, | 
 |       GetCertificate(_, _, _, _, ::attestation::KEY_TYPE_RSA, key_name, _, _)); | 
 |  | 
 |   RunOneStepAndExpect(flow_type, /*will_register_key=*/true, "", | 
 |                       TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 | } | 
 |  | 
 | TEST_F(TpmChallengeKeySubtleTestECC, UserKeyRegisteredSuccessDefaultNameECC) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const std::string key_name = std::string(kEnterpriseUserKey) + "-ecdsa"; | 
 |  | 
 |   EXPECT_CALL( | 
 |       mock_attestation_flow_, | 
 |       GetCertificate(_, _, _, _, ::attestation::KEY_TYPE_ECC, key_name, _, _)); | 
 |  | 
 |   RunOneStepAndExpect(flow_type, /*will_register_key=*/true, "", | 
 |                       TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, UserKeyNotRegisteredSuccess) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const std::string key_name = GetDefaultKeyName(flow_type); | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_username(kTestUserEmail); | 
 |   expected_request.set_key_label(GetDefaultKeyName(flow_type)); | 
 |   expected_request.set_domain(kTestUserEmail); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(false); | 
 |   expected_request.set_flow_type(::attestation::ENTERPRISE_USER); | 
 |   expected_request.set_include_certificate(true); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   RunTwoStepsAndExpect(flow_type, /*will_register_key=*/false, kEmptyKeyName, | 
 |                        TpmChallengeKeyResult::MakeChallengeResponse( | 
 |                            GetChallengeResponse(/*include_spkac=*/false))); | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, UserKeyRegisteredSuccess) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_username(kTestUserEmail); | 
 |   expected_request.set_key_label(kNonDefaultKeyName); | 
 |   expected_request.set_domain(kTestUserEmail); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(false); | 
 |   expected_request.set_flow_type(::attestation::ENTERPRISE_USER); | 
 |   expected_request.set_include_certificate(true); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   AttestationClient::Get()->GetTestInterface()->AllowlistRegisterKey( | 
 |       kTestUserEmail, key_name); | 
 |  | 
 |   EXPECT_CALL( | 
 |       *user_private_token_key_permissions_manager_, | 
 |       AllowKeyForUsage(/*callback=*/_, platform_keys::KeyUsage::kCorporate, | 
 |                        GetPublicKeyBin())) | 
 |       .WillOnce(RunOnceCallback<0>(chromeos::platform_keys::Status::kSuccess)); | 
 |  | 
 |   RunThreeStepsAndExpect(flow_type, /*will_register_key=*/true, key_name, | 
 |                          TpmChallengeKeyResult::MakeSuccess()); | 
 | } | 
 |  | 
 | TEST_P(DeviceKeysAccessTpmChallengeKeySubtleTest, SignChallengeFailed) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_MACHINE; | 
 |  | 
 |   EXPECT_CALL( | 
 |       mock_attestation_flow_, | 
 |       GetCertificate(_, _, _, _, _, GetDefaultKeyName(flow_type), _, _)); | 
 |  | 
 |   // The signing operations fails because we don't allowlist any key. | 
 |   RunTwoStepsAndExpect( | 
 |       flow_type, /*will_register_key=*/false, kEmptyKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kSignChallengeFailedError)); | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, RestorePreparedKeyState) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   // Inject mocks into the next result of CreateForPreparedKey. | 
 |   TpmChallengeKeySubtleFactory::SetForTesting( | 
 |       std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_, | 
 |                                                   &mock_cert_uploader_)); | 
 |  | 
 |   challenge_key_subtle_ = TpmChallengeKeySubtleFactory::CreateForPreparedKey( | 
 |       flow_type, /*will_register_key=*/true, ::attestation::KEY_TYPE_RSA, | 
 |       key_name, GetPublicKey(), GetProfile()); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_username(kTestUserEmail); | 
 |   expected_request.set_key_label(kNonDefaultKeyName); | 
 |   expected_request.set_domain(kTestUserEmail); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(false); | 
 |   expected_request.set_flow_type(::attestation::ENTERPRISE_USER); | 
 |   expected_request.set_include_certificate(true); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   { | 
 |     CallbackObserver callback_observer; | 
 |     challenge_key_subtle_->StartSignChallengeStep( | 
 |         GetChallenge(), callback_observer.GetCallback()); | 
 |     callback_observer.WaitForCallback(); | 
 |  | 
 |     EXPECT_EQ(callback_observer.GetResult(), | 
 |               TpmChallengeKeyResult::MakeChallengeResponse( | 
 |                   GetChallengeResponse(/*include_spkac=*/true))); | 
 |   } | 
 |  | 
 |   AttestationClient::Get()->GetTestInterface()->AllowlistRegisterKey( | 
 |       kTestUserEmail, key_name); | 
 |  | 
 |   EXPECT_CALL( | 
 |       *user_private_token_key_permissions_manager_, | 
 |       AllowKeyForUsage(/*callback=*/_, platform_keys::KeyUsage::kCorporate, | 
 |                        GetPublicKeyBin())) | 
 |       .WillOnce(RunOnceCallback<0>(chromeos::platform_keys::Status::kSuccess)); | 
 |  | 
 |   { | 
 |     CallbackObserver callback_observer; | 
 |     challenge_key_subtle_->StartRegisterKeyStep( | 
 |         callback_observer.GetCallback()); | 
 |     callback_observer.WaitForCallback(); | 
 |  | 
 |     EXPECT_EQ(callback_observer.GetResult(), | 
 |               TpmChallengeKeyResult::MakeSuccess()); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, KeyRegistrationFailed) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   // Inject mocks into the next result of CreateForPreparedKey. | 
 |   TpmChallengeKeySubtleFactory::SetForTesting( | 
 |       std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_, | 
 |                                                   &mock_cert_uploader_)); | 
 |  | 
 |   challenge_key_subtle_ = TpmChallengeKeySubtleFactory::CreateForPreparedKey( | 
 |       flow_type, /*will_register_key=*/true, ::attestation::KEY_TYPE_RSA, | 
 |       key_name, GetPublicKey(), GetProfile()); | 
 |  | 
 |   CallbackObserver callback_observer; | 
 |   challenge_key_subtle_->StartRegisterKeyStep(callback_observer.GetCallback()); | 
 |   callback_observer.WaitForCallback(); | 
 |  | 
 |   EXPECT_EQ(callback_observer.GetResult(), | 
 |             TpmChallengeKeyResult::MakeError( | 
 |                 TpmChallengeKeyResultCode::kKeyRegistrationFailedError)); | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, GetPublicKeyFailed) { | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   // Force the attestation client to report absence even after successful | 
 |   // attestation flow. | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->GetMutableKeyInfoReply(/*username=*/"", key_name) | 
 |       ->set_status(::attestation::STATUS_INVALID_PARAMETER); | 
 |  | 
 |   RunOneStepAndExpect(::attestation::ENTERPRISE_MACHINE, | 
 |                       /*will_register_key=*/true, key_name, | 
 |                       TpmChallengeKeyResult::MakeError( | 
 |                           TpmChallengeKeyResultCode::kGetPublicKeyFailedError)); | 
 | } | 
 |  | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, WaitForCertificateUploaded) { | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   using CallbackHolderT = | 
 |       CallbackHolder<MachineCertificateUploader::UploadCallback>; | 
 |   CallbackHolderT callback_holder; | 
 |   EXPECT_CALL(mock_cert_uploader_, WaitForUploadComplete) | 
 |       .WillOnce( | 
 |           testing::Invoke(&callback_holder, &CallbackHolderT::SaveCallback)); | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   CallbackObserver callback_observer; | 
 |   challenge_key_subtle_->StartPrepareKeyStep( | 
 |       ::attestation::ENTERPRISE_MACHINE, /*will_register_key=*/true, | 
 |       ::attestation::KEY_TYPE_RSA, key_name, GetProfile(), | 
 |       callback_observer.GetCallback(), | 
 |       /*signals=*/std::nullopt); | 
 |  | 
 |   // |challenge_key_subtle_| should wait until the certificate is uploaded. | 
 |   task_environment_.FastForwardBy(base::Minutes(10)); | 
 |   EXPECT_FALSE(callback_observer.IsResultReceived()); | 
 |  | 
 |   // Emulate callback from the certificate uploader, |challenge_key_subtle_| | 
 |   // should be able to continue now. | 
 |   std::move(callback_holder.callback).Run(true); | 
 |   callback_observer.WaitForCallback(); | 
 |  | 
 |   EXPECT_EQ(callback_observer.GetResult(), | 
 |             TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 | } | 
 |  | 
 | // Check that the class works when MachineCertificateUploader is not provided | 
 | // (e.g. if device is managed by Active Directory). | 
 | TEST_F(AffiliatedUserTpmChallengeKeySubtleTest, NoCertificateUploaderSuccess) { | 
 |   const char* const key_name = kNonDefaultKeyName; | 
 |  | 
 |   challenge_key_subtle_ = std::make_unique<TpmChallengeKeySubtleImpl>( | 
 |       &mock_attestation_flow_, /*machine_certificate_uploader=*/nullptr); | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   RunOneStepAndExpect(::attestation::ENTERPRISE_USER, | 
 |                       /*will_register_key=*/true, key_name, | 
 |                       TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); | 
 | } | 
 |  | 
 | // Checks that the include_customer_id field is true in kiosk sessions. | 
 | TEST_F(KioskTpmChallengeKeySubtleTest, IncludesCustomerId) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::ENTERPRISE_USER; | 
 |   const std::string key_name = GetDefaultKeyName(flow_type); | 
 |  | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, key_name, _, _)); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_username(kiosk_user_email()); | 
 |   expected_request.set_key_label(GetDefaultKeyName(flow_type)); | 
 |   expected_request.set_domain(kiosk_user_email()); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(true); | 
 |   expected_request.set_flow_type(::attestation::ENTERPRISE_USER); | 
 |   expected_request.set_include_certificate(true); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   RunTwoStepsAndExpect(flow_type, /*will_register_key=*/false, kEmptyKeyName, | 
 |                        TpmChallengeKeyResult::MakeChallengeResponse( | 
 |                            GetChallengeResponse(/*include_spkac=*/false))); | 
 | } | 
 |  | 
 | // TODO(b/277707201): remove once user email from login screen can be passed to | 
 | // TpmChallengeKeySubtle. | 
 | TEST_F(SigninProfileTpmChallengeKeySubtleTest, | 
 |        DeviceTrustConnectorProfileRequired) { | 
 |   RunOneStepAndExpect( | 
 |       ::attestation::DEVICE_TRUST_CONNECTOR, /*will_register_key=*/false, | 
 |       kNonDefaultKeyName, | 
 |       TpmChallengeKeyResult::MakeError( | 
 |           TpmChallengeKeyResultCode::kUserKeyNotAvailableError)); | 
 | } | 
 |  | 
 | TEST_F(UnmanagedUserTpmChallengeKeySubtleTest, | 
 |        DeviceTrustConnectorUserNotManaged) { | 
 |   RunOneStepAndExpect(::attestation::DEVICE_TRUST_CONNECTOR, | 
 |                       /*will_register_key=*/false, kNonDefaultKeyName, | 
 |                       TpmChallengeKeyResult::MakeError( | 
 |                           TpmChallengeKeyResultCode::kUserNotManagedError)); | 
 | } | 
 |  | 
 | TEST_F(UnaffiliatedUserTpmChallengeKeySubtleTest, DeviceTrustConnectorSuccess) { | 
 |   const ::attestation::VerifiedAccessFlow flow_type = | 
 |       ::attestation::DEVICE_TRUST_CONNECTOR; | 
 |   EXPECT_CALL(mock_attestation_flow_, | 
 |               GetCertificate(_, _, _, _, _, kNonDefaultKeyName, _, _)); | 
 |  | 
 |   ::attestation::SignEnterpriseChallengeRequest expected_request; | 
 |   expected_request.set_key_label(kNonDefaultKeyName); | 
 |   expected_request.set_domain(kTestUserEmail); | 
 |   expected_request.set_device_id(GetInstallAttributes()->GetDeviceId()); | 
 |   expected_request.set_include_customer_id(false); | 
 |   expected_request.set_flow_type(::attestation::DEVICE_TRUST_CONNECTOR); | 
 |   expected_request.set_include_certificate(true); | 
 |   AttestationClient::Get() | 
 |       ->GetTestInterface() | 
 |       ->AllowlistSignEnterpriseChallengeKey(expected_request); | 
 |  | 
 |   RunTwoStepsAndExpect(flow_type, /*will_register_key=*/false, | 
 |                        kNonDefaultKeyName, | 
 |                        TpmChallengeKeyResult::MakeChallengeResponse( | 
 |                            GetChallengeResponse(/*include_spkac=*/false))); | 
 | } | 
 |  | 
 | }  // namespace | 
 | }  // namespace attestation | 
 | }  // namespace ash |