#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>
#include "base/base64.h"
#include "base/base64url.h"
#include "base/callback_list.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/process/process.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_logging_settings.h"
#include "base/test/simple_test_clock.h"
#include "base/test/test_future.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/test/integration/sync_service_impl_harness.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_controller.h"
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
#include "chrome/browser/webauthn/enclave_manager.h"
#include "chrome/browser/webauthn/enclave_manager_factory.h"
#include "chrome/browser/webauthn/fake_magic_arch.h"
#include "chrome/browser/webauthn/fake_recovery_key_store.h"
#include "chrome/browser/webauthn/fake_security_domain_service.h"
#include "chrome/browser/webauthn/gpm_enclave_controller.h"
#include "chrome/browser/webauthn/passkey_model_factory.h"
#include "chrome/browser/webauthn/test_util.h"
#include "chrome/browser/webauthn/webauthn_pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/os_crypt/sync/os_crypt_mocker.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/protocol/webauthn_credential_specifics.pb.h"
#include "components/sync/service/sync_service.h"
#include "components/sync/service/sync_service_impl.h"
#include "components/sync/test/fake_server_network_resources.h"
#include "components/trusted_vault/securebox.h"
#include "components/trusted_vault/test/mock_trusted_vault_connection.h"
#include "components/trusted_vault/trusted_vault_connection.h"
#include "components/webauthn/core/browser/passkey_model.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "crypto/scoped_fake_user_verifying_key_provider.h"
#include "crypto/scoped_mock_unexportable_key_provider.h"
#include "crypto/unexportable_key.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/fido/enclave/constants.h"
#include "device/fido/features.h"
#include "device/fido/fido_request_handler_base.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/fido_types.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(IS_WIN)
#include "device/fido/win/fake_webauthn_api.h"
#include "device/fido/win/util.h"
#include "device/fido/win/webauthn_api.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "base/test/test_future.h"
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate_mac.h"
#include "chrome/common/chrome_version.h"
#include "components/trusted_vault/proto/vault.pb.h"
#include "components/trusted_vault/proto_string_bytes_conversion.h"
#include "crypto/scoped_fake_apple_keychain_v2.h"
#include "device/fido/enclave/icloud_recovery_key_mac.h"
#include "device/fido/mac/fake_icloud_keychain.h"
#include "device/fido/mac/util.h"
#endif
#if !defined(MEMORY_SANITIZER)
namespace {
MockTrustedVaultConnection;
constexpr int32_t kSecretVersion = …;
constexpr uint8_t kSecurityDomainSecret[32] = …;
constexpr char kEmail[] = …;
constexpr char kEmailLocalPartOnly[] = …;
constexpr char kGaiaId[] = …;
constexpr uint8_t kTestProtobuf[] = …;
base::span<const uint8_t, 16> TestProtobufCredId() { … }
static constexpr char kIsUVPAA[] = …;
static constexpr char kMakeCredentialUvDiscouraged[] = …;
static constexpr char kMakeCredentialReturnId[] = …;
static constexpr char kMakeCredentialWithExcludedCredential[] = …;
static constexpr char kMakeCredentialCrossPlatform[] = …;
static constexpr char kMakeCredentialAttachmentPlatform[] = …;
static constexpr char kMakeCredentialUvRequired[] = …;
static constexpr char kMakeCredentialWithPrf[] = …;
static constexpr char kMakeCredentialGoogle[] = …;
static constexpr char kGetAssertionWithPrf[] = …;
static constexpr char kGetAssertionUvDiscouraged[] = …;
static constexpr char kAbortableGetAssertion[] = …;
static constexpr char kAbort[] = …;
static constexpr char kGetAssertionUvDiscouragedWithCredId[] = …;
static constexpr char
kGetAssertionUvDiscouragedWithCredIdAndInternalTransport[] = …;
static constexpr char kGetAssertionUvRequired[] = …;
static constexpr char kGetAssertionUvPreferred[] = …;
static constexpr char kGetAssertionConditionalUI[] = …;
bool IsReady(GPMEnclaveController::AccountState state) { … }
bool IsMechanismEnclaveCredential(
const AuthenticatorRequestDialogModel::Mechanism& mechanism) { … }
struct TempDir { … };
class EnclaveAuthenticatorBrowserTest : public SyncTest { … };
class EnclaveAuthenticatorWithPinBrowserTest
: public EnclaveAuthenticatorBrowserTest { … };
std::tuple<bool, std::string, std::string> ParsePrfResult(
std::string_view result_view) { … }
std::optional<std::vector<uint8_t>> ParseCredentialId(
std::string_view result_view) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
RegisterDeviceWithGpmPin_MakeCredential_Success) { … }
#if BUILDFLAG(IS_MAC)
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
RegisterICloudDriveEnabled_NoGPMDefault) {
if (__builtin_available(macOS 13.5, *)) {
scoped_icloud_drive_override_.reset();
scoped_icloud_drive_override_ = OverrideICloudDriveEnabled(true);
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(
std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kMechanismSelection);
}
}
IN_PROC_BROWSER_TEST_F(
EnclaveAuthenticatorWithPinBrowserTest,
RegisterICloudDriveEnabledButAlsoPasskeyPresent_GPMDefault) {
if (__builtin_available(macOS 13.5, *)) {
scoped_icloud_drive_override_.reset();
scoped_icloud_drive_override_ = OverrideICloudDriveEnabled(true);
AddTestPasskeyToModel();
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(
std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePasskey);
}
}
IN_PROC_BROWSER_TEST_F(
EnclaveAuthenticatorWithPinBrowserTest,
RegisterICloudDriveEnabledButPermissionDenied_GPMDefault) {
if (__builtin_available(macOS 13.5, *)) {
scoped_icloud_drive_override_.reset();
scoped_icloud_drive_override_ = OverrideICloudDriveEnabled(true);
fake_icloud_keychain_.reset();
fake_icloud_keychain_ =
device::fido::icloud_keychain::NewFakeWithPermission(false);
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(
std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePasskey);
}
}
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
MacOs13_4_OrLess_GPMDefault) {
if (__builtin_available(macOS 13.5, *)) {
} else {
scoped_icloud_drive_override_.reset();
scoped_icloud_drive_override_ = OverrideICloudDriveEnabled(true);
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(
std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePasskey);
}
}
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
MakeCredentialWithPrf) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
GetAssertionWithPrf) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
RegisterDeviceWithGpmPin_MakeCredentialWithUV_Success) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
MakeCredential_RecoverWithGPMPIN_Success) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
MakeCredential_RecoverWithLSKF_Success) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
CreatingDuplicateGivesInvalidStateError) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
RecoverWithLSKF_GetAssertion_Success) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
RegisterDeviceWithGpmPin_UVRequestsWithWrongPIN) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
GpmPinRegistrationPersistAcrossRestart) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest, UserCancelsUV) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
ConditionalMediationLoading) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
SelectPasskeyAfterTimeout) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
SelectPasskeyThenTimeout) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
GpmEnclaveNeedsReauth) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
UserResetsSecurityDomain) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
SecurityDomainCheckTimesOut) { … }
class EnclaveAuthenticatorWithoutPinBrowserTest
: public EnclaveAuthenticatorBrowserTest { … };
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
#define MAYBE_NotAvailableWithoutUV …
#else
#define MAYBE_NotAvailableWithoutUV …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MAYBE_NotAvailableWithoutUV) { … }
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
#define MAYBE_NotAvailableForEmptyAccounts …
#else
#define MAYBE_NotAvailableForEmptyAccounts …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MAYBE_NotAvailableForEmptyAccounts) { … }
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
#define MAYBE_NoGpmCredentialsIfDeviceCannotBeEnrolled …
#else
#define MAYBE_NoGpmCredentialsIfDeviceCannotBeEnrolled …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MAYBE_NoGpmCredentialsIfDeviceCannotBeEnrolled) { … }
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
#define MAYBE_NotAvailableIfLskfsAreTooOld …
#else
#define MAYBE_NotAvailableIfLskfsAreTooOld …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MAYBE_NotAvailableIfLskfsAreTooOld) { … }
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
#define MAYBE_NoGpmForCrossPlatformAttachment …
#else
#define MAYBE_NoGpmForCrossPlatformAttachment …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MAYBE_NoGpmForCrossPlatformAttachment) { … }
#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
#define MAYBE_NoGpmCreationIfPasswordManagerDisabled …
#else
#define MAYBE_NoGpmCreationIfPasswordManagerDisabled …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MAYBE_NoGpmCreationIfPasswordManagerDisabled) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
EnrollAndCreate) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
GetAssertionWithPlatformUV) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
NotForSameGoogleAccount) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
IncognitoModeMakeCredential) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
IncognitoModeGetAssertion) { … }
#if BUILDFLAG(IS_MAC)
bool MacBiometricApisAvailable() {
if (__builtin_available(macOS 12, *)) {
return true;
}
return false;
}
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
BiometricsDisabledDuringRequest) {
if (!MacBiometricApisAvailable()) {
GTEST_SKIP() << "Need macOS >= 12";
}
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kRecoverable;
SetMockVaultConnectionOnRequestDelegate(std::move(registration_state_result));
security_domain_service_->pretend_there_are_members();
AddTestPasskeyToModel();
EnableUVKeySupport();
SetBiometricsEnabled(true);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kGetAssertionUvPreferred);
delegate_observer()->WaitForUI();
model_observer()->SetStepToObserve(
AuthenticatorRequestDialogModel::Step::kRecoverSecurityDomain);
model_observer()->WaitForStep();
EnclaveManagerFactory::GetAsEnclaveManagerForProfile(browser()->profile())
->StoreKeys(kGaiaId,
{std::vector<uint8_t>(std::begin(kSecurityDomainSecret),
std::end(kSecurityDomainSecret))},
kSecretVersion);
std::string script_result;
ASSERT_TRUE(message_queue.WaitForMessage(&script_result));
EXPECT_EQ(script_result, "\"webauthn: uv=true\"");
content::ExecuteScriptAsync(web_contents, kGetAssertionUvPreferred);
delegate_observer()->WaitForUI();
model_observer()->SetStepToObserve(
AuthenticatorRequestDialogModel::Step::kGPMTouchID);
model_observer()->WaitForStep();
SetBiometricsEnabled(false);
request_delegate()->dialog_model()->OnTouchIDComplete(false);
EnclaveManagerFactory::GetAsEnclaveManagerForProfile(browser()->profile())
->StoreKeys(kGaiaId,
{std::vector<uint8_t>(std::begin(kSecurityDomainSecret),
std::end(kSecurityDomainSecret))},
kSecretVersion);
ASSERT_TRUE(message_queue.WaitForMessage(&script_result));
EXPECT_EQ(script_result, "\"webauthn: uv=true\"");
}
constexpr char kICloudKeychainRecoveryKeyAccessGroup[] =
MAC_TEAM_IDENTIFIER_STRING ".com.google.common.folsom";
class EnclaveICloudRecoveryKeyTest
: public EnclaveAuthenticatorWithPinBrowserTest {
protected:
base::test::ScopedFeatureList scoped_feature_list_{
device::kWebAuthnICloudRecoveryKey};
crypto::ScopedFakeAppleKeychainV2 scoped_fake_apple_keychain_{
kICloudKeychainRecoveryKeyAccessGroup};
};
IN_PROC_BROWSER_TEST_F(EnclaveICloudRecoveryKeyTest, Enroll) {
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePasskey);
EXPECT_EQ(request_delegate()
->enclave_controller_for_testing()
->account_state_for_testing(),
GPMEnclaveController::AccountState::kEmpty);
dialog_model()->OnGPMCreatePasskey();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePin);
dialog_model()->OnGPMPinEntered(u"123456");
std::string script_result;
ASSERT_TRUE(message_queue.WaitForMessage(&script_result));
EXPECT_EQ(script_result, "\"webauthn: OK\"");
delegate_observer()->WaitForDelegateDestruction();
const auto icloud_member = std::ranges::find_if(
security_domain_service_->members(),
[](const trusted_vault_pb::SecurityDomainMember& member) {
return member.member_type() == trusted_vault_pb::SecurityDomainMember::
MEMBER_TYPE_ICLOUD_KEYCHAIN;
});
ASSERT_NE(icloud_member, security_domain_service_->members().end());
base::test::TestFuture<
std::vector<std::unique_ptr<device::enclave::ICloudRecoveryKey>>>
future;
device::enclave::ICloudRecoveryKey::Retrieve(
future.GetCallback(), kICloudKeychainRecoveryKeyAccessGroup);
EXPECT_TRUE(future.Wait());
std::vector<std::unique_ptr<device::enclave::ICloudRecoveryKey>>
recovery_keys = future.Take();
ASSERT_EQ(recovery_keys.size(), 1u);
std::unique_ptr<device::enclave::ICloudRecoveryKey> icloud_key =
std::move(recovery_keys.at(0));
EXPECT_EQ(trusted_vault::ProtoStringToBytes(icloud_member->public_key()),
icloud_key->key()->public_key().ExportToBytes());
}
IN_PROC_BROWSER_TEST_F(EnclaveICloudRecoveryKeyTest,
EnrollWithExistingKeyInICloud) {
base::test::TestFuture<std::unique_ptr<device::enclave::ICloudRecoveryKey>>
future;
device::enclave::ICloudRecoveryKey::Create(
future.GetCallback(), kICloudKeychainRecoveryKeyAccessGroup);
EXPECT_TRUE(future.Wait());
std::unique_ptr<device::enclave::ICloudRecoveryKey> existing_icloud_key =
future.Take();
ASSERT_TRUE(existing_icloud_key);
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePasskey);
EXPECT_EQ(request_delegate()
->enclave_controller_for_testing()
->account_state_for_testing(),
GPMEnclaveController::AccountState::kEmpty);
dialog_model()->OnGPMCreatePasskey();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePin);
dialog_model()->OnGPMPinEntered(u"123456");
std::string script_result;
ASSERT_TRUE(message_queue.WaitForMessage(&script_result));
EXPECT_EQ(script_result, "\"webauthn: OK\"");
delegate_observer()->WaitForDelegateDestruction();
const auto icloud_member = std::ranges::find_if(
security_domain_service_->members(),
[](const trusted_vault_pb::SecurityDomainMember& member) {
return member.member_type() == trusted_vault_pb::SecurityDomainMember::
MEMBER_TYPE_ICLOUD_KEYCHAIN;
});
ASSERT_NE(icloud_member, security_domain_service_->members().end());
EXPECT_NE(trusted_vault::ProtoStringToBytes(icloud_member->public_key()),
existing_icloud_key->key()->public_key().ExportToBytes());
base::test::TestFuture<
std::vector<std::unique_ptr<device::enclave::ICloudRecoveryKey>>>
list_future;
device::enclave::ICloudRecoveryKey::Retrieve(
list_future.GetCallback(), kICloudKeychainRecoveryKeyAccessGroup);
EXPECT_TRUE(list_future.Wait());
std::vector<std::unique_ptr<device::enclave::ICloudRecoveryKey>>
recovery_keys = list_future.Take();
EXPECT_EQ(recovery_keys.size(), 2u);
}
IN_PROC_BROWSER_TEST_F(EnclaveICloudRecoveryKeyTest, Recovery) {
{
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.state = trusted_vault::
DownloadAuthenticationFactorsRegistrationStateResult::State::kEmpty;
SetMockVaultConnectionOnRequestDelegate(
std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePasskey);
EXPECT_EQ(request_delegate()
->enclave_controller_for_testing()
->account_state_for_testing(),
GPMEnclaveController::AccountState::kEmpty);
dialog_model()->OnGPMCreatePasskey();
EXPECT_EQ(dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kGPMCreatePin);
dialog_model()->OnGPMPinEntered(u"123456");
std::string script_result;
ASSERT_TRUE(message_queue.WaitForMessage(&script_result));
EXPECT_EQ(script_result, "\"webauthn: OK\"");
delegate_observer()->WaitForDelegateDestruction();
base::test::TestFuture<
std::vector<std::unique_ptr<device::enclave::ICloudRecoveryKey>>>
future;
device::enclave::ICloudRecoveryKey::Retrieve(
future.GetCallback(), kICloudKeychainRecoveryKeyAccessGroup);
EXPECT_TRUE(future.Wait());
ASSERT_EQ(future.Get().size(), 1u);
}
EnclaveManagerFactory::GetAsEnclaveManagerForProfile(browser()->profile())
->ClearRegistrationForTesting();
EnclaveManagerFactory::GetAsEnclaveManagerForProfile(browser()->profile())
->ResetForTesting();
clock_.Advance(base::Hours(10));
{
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult
registration_state_result;
registration_state_result.gpm_pin_metadata = trusted_vault::GpmPinMetadata(
"public key",
EnclaveManager::MakeWrappedPINForTesting(kSecurityDomainSecret,
"123456"),
base::Time::Now() + base::Seconds(10000));
registration_state_result.state =
trusted_vault::DownloadAuthenticationFactorsRegistrationStateResult::
State::kRecoverable;
registration_state_result.key_version = kSecretVersion;
const auto icloud_member = std::ranges::find_if(
security_domain_service_->members(),
[](const trusted_vault_pb::SecurityDomainMember& member) {
return member.member_type() ==
trusted_vault_pb::SecurityDomainMember::
MEMBER_TYPE_ICLOUD_KEYCHAIN;
});
ASSERT_NE(icloud_member, security_domain_service_->members().end());
std::vector<trusted_vault::MemberKeys> member_keys;
auto member_key = icloud_member->memberships().at(0).keys().at(0);
member_keys.emplace_back(
member_key.epoch(),
std::vector<uint8_t>(member_key.wrapped_key().begin(),
member_key.wrapped_key().end()),
std::vector<uint8_t>(member_key.member_proof().begin(),
member_key.member_proof().end()));
registration_state_result.icloud_keys.emplace_back(
trusted_vault::SecureBoxPublicKey::CreateByImport(
std::vector<uint8_t>(icloud_member->public_key().begin(),
icloud_member->public_key().end())),
std::move(member_keys));
SetMockVaultConnectionOnRequestDelegate(
std::move(registration_state_result));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::DOMMessageQueue message_queue(web_contents);
content::ExecuteScriptAsync(web_contents, kMakeCredentialUvDiscouraged);
delegate_observer()->WaitForUI();
EXPECT_EQ(
dialog_model()->step(),
AuthenticatorRequestDialogModel::Step::kTrustThisComputerCreation);
EXPECT_EQ(request_delegate()
->enclave_controller_for_testing()
->account_state_for_testing(),
GPMEnclaveController::AccountState::kRecoverable);
dialog_model()->OnTrustThisComputer();
std::string script_result;
ASSERT_TRUE(message_queue.WaitForMessage(&script_result));
EXPECT_EQ(script_result, "\"webauthn: OK\"");
delegate_observer()->WaitForDelegateDestruction();
base::test::TestFuture<
std::vector<std::unique_ptr<device::enclave::ICloudRecoveryKey>>>
future;
device::enclave::ICloudRecoveryKey::Retrieve(
future.GetCallback(), kICloudKeychainRecoveryKeyAccessGroup);
EXPECT_TRUE(future.Wait());
ASSERT_EQ(future.Get().size(), 1u);
}
}
#endif
class EnclaveAuthenticatorCachingTest
: public EnclaveAuthenticatorWithoutPinBrowserTest { … };
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorCachingTest, Caching) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_MakeCredentialDeclineGPM …
#else
#define MAYBE_MakeCredentialDeclineGPM …
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
MAYBE_MakeCredentialDeclineGPM) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest,
MultipleDeclinedBootstrappings) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
ChangedPINDetectedWhenDoingUV) { … }
#if BUILDFLAG(IS_LINUX)
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithoutPinBrowserTest, IsUVPAA) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest, IsUVPAA) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
IsUVPAA_GoogleSite) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
IsUVPAA_NoUnexportableKeys) { … }
#endif
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
UserVerificationPolicy) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest, Bug_354083161) { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
NoSilentOperations) { … }
class BlockingUnexportableKeyProviderRendezvous { … };
BlockingUnexportableKeyProviderRendezvous&
GetBlockingUnexportableKeyProviderRendezvous() { … }
class BlockingUnexportableKeyProvider : public crypto::UnexportableKeyProvider { … };
std::unique_ptr<crypto::UnexportableKeyProvider>
BlockingUnexportableKeyProviderFactory() { … }
IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorWithPinBrowserTest,
CancelRacesTPMCheck) { … }
}
#endif