0

[WebAuthn] Stop offering GPM bootstrapping after user declines twice

If the user backs out of the GPM enclave bootstrapping screen twice
without clicking through it then we will now deprioritize it as an
option.

After that, passkey creation will not use the enclave as a priority
mechanism, although it will still be an option on the mechanism
selection screen that will allow bootstrapping if selected.

Also, synced GPM passkeys will trigger hybrid for assertions.

Bug: 40274370
Change-Id: I34604f3899bdfd169cad1930bbee1a614c792f12
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5529798
Reviewed-by: Adam Langley <agl@chromium.org>
Commit-Queue: Ken Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1299568}
This commit is contained in:
Ken Buchanan
2024-05-10 22:33:16 +00:00
committed by Chromium LUCI CQ
parent b55c686e42
commit cfa287ac7d
6 changed files with 50 additions and 4 deletions

@ -48,6 +48,7 @@
#include "content/public/browser/web_contents.h"
#include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/discoverable_credential_metadata.h"
#include "device/fido/enclave/constants.h"
#include "device/fido/enclave/metrics.h"
#include "device/fido/features.h"
#include "device/fido/fido_authenticator.h"
@ -663,9 +664,22 @@ void AuthenticatorRequestDialogController::StartFlow(
}
void AuthenticatorRequestDialogController::StartOver() {
if (enclave_was_priority_mechanism_) {
if (model_->step() == Step::kTrustThisComputerCreation ||
model_->step() == Step::kTrustThisComputerAssertion) {
auto* pref_service = Profile::FromBrowserContext(
model_->GetRenderFrameHost()->GetBrowserContext())
->GetOriginalProfile()
->GetPrefs();
int current_gpm_decline_count = pref_service->GetInteger(
webauthn::pref_names::kEnclaveDeclinedGPMBootstrappingCount);
pref_service->SetInteger(
webauthn::pref_names::kEnclaveDeclinedGPMBootstrappingCount,
std::min(current_gpm_decline_count + 1,
device::enclave::kMaxGPMBootstrapPrompts));
} else if (enclave_was_priority_mechanism_) {
auto* pref_service = Profile::FromBrowserContext(
model_->GetRenderFrameHost()->GetBrowserContext())
->GetOriginalProfile()
->GetPrefs();
int current_gpm_decline_count = pref_service->GetInteger(
webauthn::pref_names::kEnclaveDeclinedGPMCredentialCreationCount);
@ -2515,13 +2529,22 @@ AuthenticatorRequestDialogController::IndexOfPriorityMechanism() {
device::FidoRequestType::kMakeCredential);
Profile* profile = Profile::FromBrowserContext(
model_->GetRenderFrameHost()->GetBrowserContext());
model_->GetRenderFrameHost()->GetBrowserContext())
->GetOriginalProfile();
const bool enclave_decline_limit_reached =
profile->GetPrefs()->GetInteger(
webauthn::pref_names::kEnclaveDeclinedGPMCredentialCreationCount) >=
kMaxPriorityGPMCredentialCreations;
// If a user has declined bootstrapping too many times then GPM will still
// be available in the mechanism selection screen for credential creation,
// but it can no longer be a priority mechanism.
const bool enclave_bootstrap_limit_reached =
profile->GetPrefs()->GetInteger(
webauthn::pref_names::kEnclaveDeclinedGPMBootstrappingCount) >=
device::enclave::kMaxGPMBootstrapPrompts;
if (base::FeatureList::IsEnabled(device::kWebAuthnEnclaveAuthenticator) &&
!enclave_decline_limit_reached && enclave_enabled_ &&
!enclave_decline_limit_reached && !enclave_bootstrap_limit_reached &&
enclave_enabled_ &&
*transport_availability_.make_credential_attachment ==
device::AuthenticatorAttachment::kPlatform) {
priority_list.emplace_back(Mechanism::Enclave());

@ -615,6 +615,8 @@ void ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(
registry->RegisterListPref(prefs::kSecurityKeyPermitAttestation);
registry->RegisterIntegerPref(
webauthn::pref_names::kEnclaveDeclinedGPMCredentialCreationCount, 0);
registry->RegisterIntegerPref(
webauthn::pref_names::kEnclaveDeclinedGPMBootstrappingCount, 0);
#if BUILDFLAG(IS_WIN)
LocalCredentialManagementWin::RegisterProfilePrefs(registry);
#endif
@ -1388,7 +1390,14 @@ void ChromeAuthenticatorRequestDelegate::GetPhoneContactableGpmPasskeysForRpId(
credentials = chromeos_passkey_controller_->credentials();
type = device::AuthenticatorType::kChromeOSPasskeys;
#else
if (enclave_controller_) {
int enclave_bootstrap_limit_reached =
Profile::FromBrowserContext(GetBrowserContext())
->GetOriginalProfile()
->GetPrefs()
->GetInteger(
webauthn::pref_names::kEnclaveDeclinedGPMBootstrappingCount) >=
device::enclave::kMaxGPMBootstrapPrompts;
if (enclave_controller_ && !enclave_bootstrap_limit_reached) {
credentials = enclave_controller_->creds();
type = device::AuthenticatorType::kEnclave;
#endif

@ -901,6 +901,10 @@ void GPMEnclaveController::OnTrustThisComputer() {
model_->SetStep(Step::kGPMConfirmOffTheRecordCreate);
return;
}
Profile::FromBrowserContext(model_->GetRenderFrameHost()->GetBrowserContext())
->GetPrefs()
->SetInteger(webauthn::pref_names::kEnclaveDeclinedGPMBootstrappingCount,
0);
model_->SetStep(Step::kRecoverSecurityDomain);
}

@ -11,6 +11,9 @@ const char kAllowWithBrokenCerts[] = "webauthn.allow_with_broken_certs";
const char kEnclaveDeclinedGPMCredentialCreationCount[] =
"webauthn.enclave_declined_gpm_credential_creation_count";
const char kEnclaveDeclinedGPMBootstrappingCount[] =
"webauthn.enclave_declined_gpm_bootstrapping_count";
const char kEnclaveFailedPINAttemptsCount[] =
"webauthn.enclave_failed_pin_attempts_count";

@ -15,6 +15,9 @@ extern const char kAllowWithBrokenCerts[];
// request.
extern const char kEnclaveDeclinedGPMCredentialCreationCount[];
// Tracks how many times a user has declined GPM bootstrapping on this device.
extern const char kEnclaveDeclinedGPMBootstrappingCount[];
// Tracks how many consecutive failed GPM PIN attempts have been made to the
// enclave service from this device and profile.
extern const char kEnclaveFailedPINAttemptsCount[];

@ -45,6 +45,10 @@ inline constexpr size_t kCounterIDLen = 8;
// The length of a recovery key store "vault handle" value.
inline constexpr size_t kVaultHandleLen = 17;
// The maximum number of times that GPM enclave bootstrapping can be declined
// before it becomes deprioritized as an authenticator option.
inline constexpr int kMaxGPMBootstrapPrompts = 2;
// The list of algorithms that are acceptable as device identity keys.
inline constexpr crypto::SignatureVerifier::SignatureAlgorithm
kSigningAlgorithms[] = {