// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cryptohome/userdataauth.h"

#include <algorithm>
#include <limits>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <absl/cleanup/cleanup.h>
#include <absl/strings/numbers.h>
#include <attestation/proto_bindings/pca_agent.pb.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file_path.h>
#include <base/functional/bind.h>
#include <base/functional/callback.h>
#include <base/functional/callback_forward.h>
#include <base/functional/callback_helpers.h>
#include <base/json/json_writer.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/message_loop/message_pump_type.h>
#include <base/notreached.h>
#include <base/rand_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/task/single_thread_task_runner.h>
#include <base/time/time.h>
#include <base/unguessable_token.h>
#include <biod/biod_proxy/auth_stack_manager_proxy_base.h>
#include <bootlockbox/boot_lockbox_client.h>
#include <brillo/cryptohome.h>
#include <brillo/secure_blob.h>
#include <chaps/isolate.h>
#include <chaps/token_manager_client.h>
#include <chromeos/constants/cryptohome.h>
#include <cryptohome/proto_bindings/auth_factor.pb.h>
#include <cryptohome/proto_bindings/recoverable_key_store.pb.h>
#include <cryptohome/proto_bindings/UserDataAuth.pb.h>
#include <dbus/cryptohome/dbus-constants.h>
#include <dbus_adaptors/org.chromium.UserDataAuth.h>
#include <device_management/proto_bindings/device_management_interface.pb.h>
#include <device_management-client/device_management/dbus-proxies.h>
#include <featured/feature_library.h>
#include <libhwsec/factory/factory_impl.h>
#include <libhwsec/status.h>
#include <libhwsec-foundation/crypto/secure_blob_util.h>
#include <libhwsec-foundation/crypto/sha.h>
#include <libhwsec-foundation/status/status_chain.h>
#include <libhwsec-foundation/status/status_chain_macros.h>
#include <libhwsec-foundation/utility/task_dispatching_framework.h>
#include <libstorage/platform/platform.h>
#include <metrics/timer.h>
#include <pca_agent-client/pca_agent/dbus-proxies.h>

#include "cryptohome/auth_blocks/auth_block_utility_impl.h"
#include "cryptohome/auth_blocks/biometrics_command_processor_impl.h"
#include "cryptohome/auth_blocks/fp_service.h"
#include "cryptohome/auth_factor/auth_factor.h"
#include "cryptohome/auth_factor/flatbuffer.h"
#include "cryptohome/auth_factor/manager.h"
#include "cryptohome/auth_factor/protobuf.h"
#include "cryptohome/auth_factor/storage_type.h"
#include "cryptohome/auth_factor/type.h"
#include "cryptohome/auth_factor/types/manager.h"
#include "cryptohome/auth_factor/with_driver.h"
#include "cryptohome/auth_io/auth_input.h"
#include "cryptohome/auth_io/prepare_output.h"
#include "cryptohome/auth_session/auth_session.h"
#include "cryptohome/auth_session/flatbuffer.h"
#include "cryptohome/auth_session/intent.h"
#include "cryptohome/auth_session/manager.h"
#include "cryptohome/auth_session/protobuf.h"
#include "cryptohome/challenge_credentials/challenge_credentials_helper_impl.h"
#include "cryptohome/cleanup/disk_cleanup.h"
#include "cryptohome/cleanup/low_disk_space_handler.h"
#include "cryptohome/cleanup/user_oldest_activity_timestamp_manager.h"
#include "cryptohome/create_vault_keyset_rpc_impl.h"
#include "cryptohome/credential_verifier.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/cryptorecovery/recovery_crypto_impl.h"
#include "cryptohome/error/converter.h"
#include "cryptohome/error/cryptohome_crypto_error.h"
#include "cryptohome/error/cryptohome_error.h"
#include "cryptohome/filesystem_layout.h"
#include "cryptohome/fp_migration/utility.h"
#include "cryptohome/key_challenge_service_factory.h"
#include "cryptohome/keyset_management.h"
#include "cryptohome/pkcs11/real_pkcs11_token_factory.h"
#include "cryptohome/recoverable_key_store/backend_cert_provider.h"
#include "cryptohome/recoverable_key_store/backend_cert_provider_impl.h"
#include "cryptohome/signalling.h"
#include "cryptohome/storage/cryptohome_vault.h"
#include "cryptohome/storage/mount.h"
#include "cryptohome/storage/mount_constants.h"
#include "cryptohome/user_secret_stash/manager.h"
#include "cryptohome/user_session/real_user_session_factory.h"
#include "cryptohome/user_session/user_session.h"
#include "cryptohome/username.h"
#include "cryptohome/util/proto_enum.h"

using base::FilePath;
using brillo::Blob;
using brillo::SecureBlob;
using brillo::cryptohome::home::SanitizeUserName;
using cryptohome::error::CryptohomeCryptoError;
using cryptohome::error::CryptohomeError;
using cryptohome::error::CryptohomeMountError;
using cryptohome::error::CryptohomeTPMError;
using cryptohome::error::ErrorActionSet;
using cryptohome::error::PossibleAction;
using cryptohome::error::PrimaryAction;
using hwsec::TPMErrorBase;
using hwsec::TPMRetryAction;
using hwsec_foundation::Sha1;
using hwsec_foundation::status::MakeStatus;
using hwsec_foundation::status::OkStatus;
using hwsec_foundation::status::StatusChain;

namespace cryptohome {

namespace {

constexpr char kMountThreadName[] = "MountThread";
constexpr char kNotFirstBootFilePath[] = "/run/cryptohome/not_first_boot";
constexpr char kEncDeviceEvictedPath[] = "/run/cryptohome/device_evicted";
// For enhanced security, PinWeaver pairing key establishment is blocked after
// the first user login event in each boot cycle. An ephemeral flag file is used
// to allow tracking this status.
constexpr char kPinweaverPkEstablishmentBlocked[] =
    "/run/cryptohome/pw_pk_establishment_blocked";
constexpr char kDeviceMapperDevicePrefix[] = "/dev/mapper/dmcrypt";
constexpr base::TimeDelta kDefaultExtensionTime = base::Seconds(60);
// Some utility functions used by UserDataAuth.

// Wrapper function for the ReplyWithError. |unused_auth_session| parameter is
// used for keeping the session alive until the operation has completed.
template <typename ReplyType>
void ReplyWithStatus(InUseAuthSession unused_auth_session,
                     UserDataAuth::OnDoneCallback<ReplyType> on_done,
                     CryptohomeStatus status) {
  ReplyType reply;
  ReplyWithError(std::move(on_done), std::move(reply), std::move(status));
}

// Function that can be used to inject the sending of an auth completion signal
// to an on_done callback. The function requires a copy of the start signal that
// it uses as a template for the completion signal.
template <typename ReplyType>
void SignalAuthCompletedThenDone(
    SignallingInterface* signalling,
    user_data_auth::AuthenticateStarted start_signal,
    UserDataAuth::OnDoneCallback<ReplyType> on_done,
    const ReplyType& reply) {
  user_data_auth::AuthenticateAuthFactorCompleted signal;
  signal.set_operation_id(start_signal.operation_id());
  if (reply.has_error_info()) {
    signal.set_error(reply.error());
    *signal.mutable_error_info() = reply.error_info();
  }

  signal.set_username(start_signal.username());
  signal.set_sanitized_username(start_signal.sanitized_username());

  switch (start_signal.auth_factor_case()) {
    case user_data_auth::AuthenticateStarted::kAuthFactorType:
      signal.set_auth_factor_type(start_signal.auth_factor_type());
      break;
    case user_data_auth::AuthenticateStarted::kUserCreation:
      signal.set_user_creation(start_signal.user_creation());
      break;
    case user_data_auth::AuthenticateStarted::AUTH_FACTOR_NOT_SET:
      break;
  }

  signalling->SendAuthenticateAuthFactorCompleted(signal);
  std::move(on_done).Run(reply);
}

// Function that can be used to inject the sending of a mount completion signal
// to an on_done callback. The function requires a copy of the start signal that
// it uses as a template for the completion signal.
template <typename ReplyType>
void SignalMountCompletedThenDone(
    SignallingInterface* signalling,
    user_data_auth::MountStarted start_signal,
    UserDataAuth::OnDoneCallback<ReplyType> on_done,
    const ReplyType& reply) {
  user_data_auth::MountCompleted signal;
  signal.set_operation_id(start_signal.operation_id());
  if (reply.has_error_info()) {
    signal.set_error(reply.error());
    *signal.mutable_error_info() = reply.error_info();
  }
  signalling->SendMountCompleted(signal);
  std::move(on_done).Run(reply);
}

// This function returns the AuthFactorPolicy from the UserPolicy. It will
// return an empty policy if the user policy doesn't exist, or if the
// auth_factor_type doesn't exist in the user policy.
SerializedUserAuthFactorTypePolicy GetAuthFactorPolicyFromUserPolicy(
    const std::optional<SerializedUserPolicy>& user_policy,
    AuthFactorType auth_factor_type) {
  if (!user_policy.has_value()) {
    return GetEmptyAuthFactorTypePolicy(auth_factor_type);
  }
  for (auto policy : user_policy->auth_factor_type_policy) {
    if (policy.type != std::nullopt &&
        policy.type == SerializeAuthFactorType(auth_factor_type)) {
      return policy;
    }
  }
  return GetEmptyAuthFactorTypePolicy(auth_factor_type);
}

// This function sets the auth intents for auth factor type. As long as an
// intent is supported it should be included in the maximal set. The minimal set
// only includes supported non-configurable intents. If a policy has been set
// for the auth factor type, the set policy should be used as the "current" set,
// otherwise supported intents that are enabled are considered the "current"
// set.
void SetAuthIntentsForAuthFactorType(
    const AuthFactorType& type,
    const AuthFactorDriver& factor_driver,
    std::optional<SerializedUserAuthFactorTypePolicy> type_policy,
    bool is_persistent_user,
    bool is_ephemeral_user,
    user_data_auth::AuthIntentsForAuthFactorType* intents_for_type) {
  intents_for_type->set_type(AuthFactorTypeToProto(type));

  for (AuthIntent intent : kAllAuthIntents) {
    // Determine if this intent can be used with this factor type for this
    // user. The check depends on the user type as full auth is only available
    // for persistent users.
    bool intent_is_supported;
    if (is_persistent_user) {
      intent_is_supported = factor_driver.IsFullAuthSupported(intent) ||
                            factor_driver.IsLightAuthSupported(intent);
    } else if (is_ephemeral_user) {
      intent_is_supported = factor_driver.IsLightAuthSupported(intent);
    } else {
      intent_is_supported = false;
    }
    // If the intent is supported, determine which of the "current, min, max"
    // sets it belongs in based on the configuration.
    if (intent_is_supported) {
      user_data_auth::AuthIntent proto_intent = AuthIntentToProto(intent);
      // The maximum contains all supported intents, always add to it.
      intents_for_type->add_maximum(proto_intent);
      // The minimum contains only the non-configurable supported intents.
      AuthFactorDriver::IntentConfigurability intent_configurability =
          factor_driver.GetIntentConfigurability(intent);
      if (intent_configurability ==
          AuthFactorDriver::IntentConfigurability::kNotConfigurable) {
        intents_for_type->add_minimum(proto_intent);
        // If an intent is not configurable and is supported it should be
        // included in the current set of intents regardless of a new type
        // policy being applied or not.
        intents_for_type->add_current(proto_intent);
      }
      // Unless there is a policy set for the user, the current set contains
      // supported intents which are enabled by default as well as
      // notconfigurable ones.
      if (!type_policy.has_value() &&
          intent_configurability ==
              AuthFactorDriver::IntentConfigurability::kEnabledByDefault) {
        intents_for_type->add_current(proto_intent);
      }
    }
  }
  // if there is a policy in place for this auth factor type, use the policy as
  // the "current" intent.
  if (type_policy.has_value()) {
    for (auto intent : type_policy->enabled_intents) {
      intents_for_type->add_current(
          AuthIntentToProto(DeserializeAuthIntent(intent)));
    }
  }
}

// Builder function for AuthFactorWithStatus. This function takes into account
// type and calls various library functions needed to convert AuthFactor to a
// proto for a persistent user.
std::optional<user_data_auth::AuthFactorWithStatus> GetAuthFactorWithStatus(
    const ObfuscatedUsername& username,
    UserPolicyFile* user_policy_file,
    AuthFactorDriverManager* auth_factor_driver_manager,
    const AuthFactor& auth_factor) {
  const AuthFactorDriver& factor_driver =
      auth_factor_driver_manager->GetDriver(auth_factor.type());
  auto auth_factor_proto =
      factor_driver.ConvertToProto(auth_factor.label(), auth_factor.metadata());
  if (!auth_factor_proto) {
    return std::nullopt;
  }
  user_data_auth::AuthFactorWithStatus auth_factor_with_status;
  *auth_factor_with_status.mutable_auth_factor() =
      std::move(*auth_factor_proto);
  auto supported_intents = GetSupportedIntents(
      username, auth_factor.type(), *auth_factor_driver_manager,
      GetAuthFactorPolicyFromUserPolicy(user_policy_file->GetUserPolicy(),
                                        auth_factor.type()),
      /*only_light_auth=*/false);
  for (const auto& auth_intent : supported_intents) {
    auth_factor_with_status.add_available_for_intents(
        AuthIntentToProto(auth_intent));
  }
  user_data_auth::StatusInfo& status_info =
      *auth_factor_with_status.mutable_status_info();
  auto delay = factor_driver.GetFactorDelay(username, auth_factor);
  if (delay.ok()) {
    status_info.set_time_available_in(delay->is_max()
                                          ? std::numeric_limits<uint64_t>::max()
                                          : delay->InMilliseconds());
  } else {
    // Error in getting factor lockout delay, treat it as immediately available.
    status_info.set_time_available_in(0);
  }
  auto expiration_delay =
      factor_driver.GetTimeUntilExpiration(username, auth_factor);
  if (expiration_delay.ok()) {
    status_info.set_time_expiring_in(expiration_delay->InMilliseconds());
  } else {
    // Error in getting the expiration time. Treat it as won't expire.
    status_info.set_time_expiring_in(std::numeric_limits<uint64_t>::max());
  }
  return auth_factor_with_status;
}

// Builder function for AuthFactorWithStatus for ephemeral users. This function
// takes into account type and calls various library functions needed to convert
// AuthFactor to a proto.
std::optional<user_data_auth::AuthFactorWithStatus> GetAuthFactorWithStatus(
    const ObfuscatedUsername& username,
    UserPolicyFile* user_policy_file,
    AuthFactorDriverManager* auth_factor_driver_manager,
    const CredentialVerifier* verifier) {
  const AuthFactorDriver& factor_driver =
      auth_factor_driver_manager->GetDriver(verifier->auth_factor_type());
  auto proto_factor = factor_driver.ConvertToProto(
      verifier->auth_factor_label(), verifier->auth_factor_metadata());
  if (!proto_factor) {
    LOG(INFO) << "Could not convert";
    return std::nullopt;
  }
  user_data_auth::AuthFactorWithStatus auth_factor_with_status;
  *auth_factor_with_status.mutable_auth_factor() = std::move(*proto_factor);
  auto supported_intents = GetSupportedIntents(
      username, verifier->auth_factor_type(), *auth_factor_driver_manager,
      GetAuthFactorPolicyFromUserPolicy(user_policy_file->GetUserPolicy(),
                                        verifier->auth_factor_type()),
      /*only_light_auth=*/true);
  for (const auto& auth_intent : supported_intents) {
    auth_factor_with_status.add_available_for_intents(
        AuthIntentToProto(auth_intent));
  }

  // Ephemeral user's credential won't lock out (always available) and won't
  // expire either.
  user_data_auth::StatusInfo& status_info =
      *auth_factor_with_status.mutable_status_info();
  status_info.set_time_available_in(0);
  status_info.set_time_expiring_in(std::numeric_limits<uint64_t>::max());
  return auth_factor_with_status;
}

// Overload that takes a reply type and returns the mutable AuthFactor message
// from it. Basically just calls mutable_X for whatever field "X" is the
// AuthFactorWithStatus from the reply. There must be an overload for a type to
// work with ReplyWithAuthFactorStatus.
user_data_auth::AuthFactorWithStatus* MutableAuthFactorForReplyType(
    user_data_auth::AddAuthFactorReply& reply) {
  return reply.mutable_added_auth_factor();
}
user_data_auth::AuthFactorWithStatus* MutableAuthFactorForReplyType(
    user_data_auth::UpdateAuthFactorReply& reply) {
  return reply.mutable_updated_auth_factor();
}
user_data_auth::AuthFactorWithStatus* MutableAuthFactorForReplyType(
    user_data_auth::UpdateAuthFactorMetadataReply& reply) {
  return reply.mutable_updated_auth_factor();
}
user_data_auth::AuthFactorWithStatus* MutableAuthFactorForReplyType(
    user_data_auth::RelabelAuthFactorReply& reply) {
  return reply.mutable_relabelled_auth_factor();
}
user_data_auth::AuthFactorWithStatus* MutableAuthFactorForReplyType(
    user_data_auth::ReplaceAuthFactorReply& reply) {
  return reply.mutable_replacement_auth_factor();
}

// Wrapper function for the ReplyWithError for AddAuthFactorReply,
// UpdateAuthFactorMetadata and UpdateAuthFactorWithReply.
template <typename ReplyType>
void ReplyWithAuthFactorStatus(
    InUseAuthSession auth_session,
    UserPolicyFile* user_policy_file,
    AuthFactorManager* auth_factor_manager,
    AuthFactorDriverManager* auth_factor_driver_manager,
    UserSession* user_session,
    std::string auth_factor_label,
    UserDataAuth::OnDoneCallback<ReplyType> on_done,
    CryptohomeStatus status) {
  ReplyType reply;
  if (!status.ok()) {
    ReplyWithError(std::move(on_done), std::move(reply), std::move(status));
    return;
  }
  if (CryptohomeStatus session_status = auth_session.AuthSessionStatus();
      !session_status.ok()) {
    ReplyWithError(std::move(on_done), std::move(reply),
                   std::move(session_status));
    return;
  }

  // This should always be set.
  CHECK(auth_factor_driver_manager);

  std::optional<user_data_auth::AuthFactorWithStatus> auth_factor_with_status;
  // Select which AuthFactorWithStatus to build based on user type.
  const ObfuscatedUsername& username = auth_session->obfuscated_username();
  if (auth_session->ephemeral_user()) {
    CHECK(user_session);
    auth_factor_with_status = GetAuthFactorWithStatus(
        username, user_policy_file, auth_factor_driver_manager,
        user_session->FindCredentialVerifier(auth_factor_label));
  } else {
    auth_factor_with_status = GetAuthFactorWithStatus(
        username, user_policy_file, auth_factor_driver_manager,
        auth_factor_manager->GetAuthFactorMap(username)
            .Find(auth_factor_label)
            ->auth_factor());
  }

  if (!auth_factor_with_status.has_value()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthProtoFailureInReplyWithAuthFactorStatus),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }
  *MutableAuthFactorForReplyType(reply) = std::move(*auth_factor_with_status);
  ReplyWithError(std::move(on_done), std::move(reply), std::move(status));
}

// Get the Account ID for an AccountIdentifier proto.
Username GetAccountId(const AccountIdentifier& id) {
  if (id.has_account_id()) {
    return Username(id.account_id());
  }
  return Username(id.email());
}

// Returns true if any of the path in |prefixes| starts with |path|
// Note that this function is case insensitive
bool PrefixPresent(const std::vector<FilePath>& prefixes,
                   const std::string path) {
  return std::any_of(
      prefixes.begin(), prefixes.end(), [&path](const FilePath& prefix) {
        return base::StartsWith(path, prefix.value(),
                                base::CompareCase::INSENSITIVE_ASCII);
      });
}

// Groups dm-crypt mounts for each user. Mounts for a user may have a source
// in either dmcrypt-<>-data or dmcrypt-<>-cache. Strip the application
// specific suffix for the device and use <> as the group key.
void GroupDmcryptDeviceMounts(
    std::multimap<const FilePath, const FilePath>* mounts,
    std::multimap<const FilePath, const FilePath>* grouped_mounts) {
  for (const auto& mount : *mounts) {
    // Group dmcrypt-<>-data and dmcrypt-<>-cache mounts. Strip out last
    // '-' from the path.
    size_t last_component_index = mount.first.value().find_last_of("-");

    if (last_component_index == std::string::npos) {
      continue;
    }

    base::FilePath device_group(
        mount.first.value().substr(0, last_component_index));
    if (device_group.ReferencesParent()) {
      // This should probably never occur in practice, but seems useful from
      // the security hygiene perspective to explicitly prevent transforming
      // stuff like "/foo/..-" into "/foo/..".
      LOG(WARNING) << "Skipping malformed dm-crypt mount point: "
                   << mount.first;
      continue;
    }
    grouped_mounts->insert({device_group, mount.second});
  }
}

// Fill AuthSessionProperties in auth_session_props.
void PopulateAuthSessionProperties(
    InUseAuthSession& auth_session,
    user_data_auth::AuthSessionProperties* auth_session_props) {
  for (const AuthIntent auth_intent : auth_session->authorized_intents()) {
    auth_session_props->add_authorized_for(AuthIntentToProto(auth_intent));
  }

  if (auth_session->authorized_intents().contains(AuthIntent::kDecrypt)) {
    auth_session_props->set_seconds_left(
        auth_session.GetRemainingTime().InSeconds());
  }
}

void HandleAuthenticationResult(
    InUseAuthSession auth_session,
    const SerializedUserAuthFactorTypePolicy& user_policy,
    UserDataAuth::OnDoneCallback<user_data_auth::AuthenticateAuthFactorReply>
        on_done,
    const AuthSession::PostAuthAction& post_auth_action,
    CryptohomeStatus status) {
  user_data_auth::AuthenticateAuthFactorReply reply;
  if (CryptohomeStatus session_status = auth_session.AuthSessionStatus();
      !session_status.ok()) {
    // Unfortunately if the session was timed out then regardless of the
    // post-auth actions we cannot actually execute them because we no longer
    // have a session to take them with. Just return the timeout error and stop.
    ReplyWithError(std::move(on_done), std::move(reply),
                   std::move(session_status));
    return;
  }

  // If we get here we have a valid session. Fill out the reply with it.
  PopulateAuthSessionProperties(auth_session, reply.mutable_auth_properties());
  bool auth_succeeded = status.ok();
  ReplyWithError(std::move(on_done), std::move(reply), std::move(status));

  // Reset LE credentials if authentication succeeded. Note that this requires a
  // decrypted USS so verify-only intent auth might not be able to reset LE
  // successfully here. Verify-only intent auth sets the PostAuthAction as
  // kRepeat to repeat the authentication but forcing full decrypt, such that
  // the repeated auth will be able to reset LE credentials.
  if (auth_succeeded) {
    auth_session->ResetLECredentials();
  }

  // The reply is sent, carry out any post-auth actions.
  switch (post_auth_action.action_type) {
    case AuthSession::PostAuthActionType::kNone:
      return;
    case AuthSession::PostAuthActionType::kRepeat: {
      if (!post_auth_action.repeat_request.has_value()) {
        LOG(DFATAL)
            << "PostAuthActionType::kRepeat with null repeat_request field.";
        return;
      }
      // HandleAuthenticationResult will be used as the callback to ensure the
      // repeated auth is handled identically to an ordinary auth request. The
      // implementation logic should ensure that repeated auth would not set
      // post-auth action to kRepeat again, otherwise there might be infinite
      // recursion.
      AuthSession* auth_session_ptr = auth_session.Get();
      auth_session_ptr->AuthenticateAuthFactor(
          post_auth_action.repeat_request.value(), user_policy,
          base::BindOnce(&HandleAuthenticationResult,
                         std::move(auth_session).BindForCallback(), user_policy,
                         base::DoNothing()));
      return;
    }
    case AuthSession::PostAuthActionType::kReprepare: {
      if (!post_auth_action.reprepare_request.has_value()) {
        LOG(DFATAL) << "PostAuthActionType::kReprepare with null "
                       "reprepare_request field.";
        return;
      }
      AuthSession* auth_session_ptr = auth_session.Get();
      auth_session_ptr->PrepareAuthFactor(
          post_auth_action.reprepare_request.value(),
          base::BindOnce(
              [](InUseAuthSession unused_auth_session,
                 CryptohomeStatus status) {
                if (!status.ok()) {
                  LOG(ERROR) << "Reprepare failed after an "
                                "authentication attempt: "
                             << std::move(status);
                }
              },
              std::move(auth_session).BindForCallback()));
      return;
    }
  }
}

// Wrapper around AuthSessionManager::RunWhenAvailable that will execute the
// given block of code with the in use session if the session has an OK status.
// The call expects to be given:
//  - the AuthSession manager
//  - a location to wrap the error with if the session is not OK
//  - the on_done callback for the request
//  - a run_with callback that consists of the actual handler
// The run_with callback can assume that the InUseAuthSession object that it is
// given is OK, i.e. CHECK(auth_session.AuthSessionStatus().ok()).
//
// By default the function will select the session token from an auth_session_id
// field in the request. However, there is also an overload that accepts an
// explicit token argument for use in cases where the request has no such field,
// or where the session ID is selected in some other way.
template <typename RequestType, typename ReplyType, typename TokenType>
void RunWithAuthSessionWhenAvailable(
    AuthSessionManager* auth_session_manager,
    CryptohomeError::ErrorLocationPair err_loc,
    const TokenType& token,
    RequestType request,
    UserDataAuth::OnDoneCallback<ReplyType> on_done,
    UserDataAuth::HandlerWithSessionCallback<RequestType, ReplyType> run_with) {
  // Wrap run_with in a callback which will check if InUseAuthSession is OK. If
  // the session is not okay then call ReplyWithError, wrapping the session
  // status. Otherwise, call run_with and pass on all of the parameters.
  auth_session_manager->RunWhenAvailable(
      token,
      base::BindOnce(
          [](CryptohomeError::ErrorLocationPair err_loc, RequestType request,
             UserDataAuth::OnDoneCallback<ReplyType> on_done,
             UserDataAuth::HandlerWithSessionCallback<RequestType, ReplyType>
                 run_with,
             InUseAuthSession auth_session) {
            CryptohomeStatus status = auth_session.AuthSessionStatus();
            if (!status.ok()) {
              ReplyWithError(
                  std::move(on_done), ReplyType{},
                  MakeStatus<CryptohomeError>(
                      err_loc,
                      ErrorActionSet(
                          {PossibleAction::kDevCheckUnexpectedState}),
                      user_data_auth::CryptohomeErrorCode::
                          CRYPTOHOME_INVALID_AUTH_SESSION_TOKEN)
                      .Wrap(std::move(status).err_status()));
              return;
            }
            std::move(run_with).Run(std::move(request), std::move(on_done),
                                    std::move(auth_session));
          },
          std::move(err_loc), std::move(request), std::move(on_done),
          std::move(run_with)));
}
template <typename RequestType, typename ReplyType>
void RunWithAuthSessionWhenAvailable(
    AuthSessionManager* auth_session_manager,
    CryptohomeError::ErrorLocationPair err_loc,
    RequestType request,
    UserDataAuth::OnDoneCallback<ReplyType> on_done,
    UserDataAuth::HandlerWithSessionCallback<RequestType, ReplyType> run_with) {
  std::string auth_session_id = request.auth_session_id();
  RunWithAuthSessionWhenAvailable(auth_session_manager, std::move(err_loc),
                                  auth_session_id, std::move(request),
                                  std::move(on_done), std::move(run_with));
}

// Wrapper around AuthSessionManager::RunWhenAvailable that provides all of the
// same functions as RunWithAuthSessionWhenAvailable but in addition will also
// enforce that the session is authenticated for decryption. As such it also
// takes an extra second location to use when the session exists and is OK but
// is not authenticated.
template <typename RequestType, typename ReplyType>
void RunWithAuthorizedAuthSessionWhenAvailable(
    AuthIntent intent,
    AuthSessionManager* auth_session_manager,
    CryptohomeError::ErrorLocationPair not_ok_err_loc,
    CryptohomeError::ErrorLocationPair not_auth_err_loc,
    RequestType request,
    UserDataAuth::OnDoneCallback<ReplyType> on_done,
    UserDataAuth::HandlerWithSessionCallback<RequestType, ReplyType> run_with) {
  // Wrap run_with in a callback which will check if InUseAuthSession is OK and
  // if the session is authenticated. If the session is not okay or not
  // authenticated then call ReplyWithError, wrapping the session status.
  // Otherwise, call run_with and pass on all of the parameters.
  std::string auth_session_id = request.auth_session_id();
  auth_session_manager->RunWhenAvailable(
      auth_session_id,
      base::BindOnce(
          [](AuthIntent intent,
             CryptohomeError::ErrorLocationPair not_ok_err_loc,
             CryptohomeError::ErrorLocationPair not_auth_err_loc,
             RequestType request,
             UserDataAuth::OnDoneCallback<ReplyType> on_done,
             UserDataAuth::HandlerWithSessionCallback<RequestType, ReplyType>
                 run_with,
             InUseAuthSession auth_session) {
            CryptohomeStatus status = auth_session.AuthSessionStatus();
            if (!status.ok()) {
              ReplyWithError(
                  std::move(on_done), ReplyType{},
                  MakeStatus<CryptohomeError>(
                      not_ok_err_loc,
                      ErrorActionSet(
                          {PossibleAction::kDevCheckUnexpectedState}),
                      user_data_auth::CryptohomeErrorCode::
                          CRYPTOHOME_INVALID_AUTH_SESSION_TOKEN)
                      .Wrap(std::move(status).err_status()));
              return;
            }
            if (!auth_session->authorized_intents().contains(intent)) {
              ReplyWithError(
                  std::move(on_done), ReplyType{},
                  MakeStatus<CryptohomeError>(
                      not_auth_err_loc,
                      ErrorActionSet(
                          {PossibleAction::kDevCheckUnexpectedState}),
                      user_data_auth::CryptohomeErrorCode::
                          CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
              return;
            }
            std::move(run_with).Run(std::move(request), std::move(on_done),
                                    std::move(auth_session));
          },
          intent, std::move(not_ok_err_loc), std::move(not_auth_err_loc),
          std::move(request), std::move(on_done), std::move(run_with)));
}

std::optional<user_data_auth::VaultEncryptionType>
MountTypeToVaultEncryptionType(cryptohome::MountType mount_type) {
  switch (mount_type) {
    case cryptohome::MountType::NONE:
    case cryptohome::MountType::EPHEMERAL:
      return std::nullopt;
    case cryptohome::MountType::DMCRYPT:
      return user_data_auth::VaultEncryptionType::
          CRYPTOHOME_VAULT_ENCRYPTION_DMCRYPT;
    case cryptohome::MountType::ECRYPTFS:
    case cryptohome::MountType::ECRYPTFS_TO_DIR_CRYPTO:
    case cryptohome::MountType::ECRYPTFS_TO_DMCRYPT:
      return user_data_auth::VaultEncryptionType::
          CRYPTOHOME_VAULT_ENCRYPTION_ECRYPTFS;
    case cryptohome::MountType::DIR_CRYPTO:
    case cryptohome::MountType::DIR_CRYPTO_TO_DMCRYPT:
      return user_data_auth::VaultEncryptionType::
          CRYPTOHOME_VAULT_ENCRYPTION_FSCRYPT;
      break;
  }
}

}  // namespace

UserDataAuth::UserDataAuth(BackingApis apis)
    : origin_thread_id_(base::PlatformThread::CurrentId()),
      platform_(apis.platform),
      hwsec_(apis.hwsec),
      hwsec_pw_manager_(apis.hwsec_pw_manager),
      recovery_crypto_(apis.recovery_crypto),
      cryptohome_keys_manager_(apis.cryptohome_keys_manager),
      crypto_(apis.crypto),
      recovery_ab_service_(apis.recovery_ab_service),
      default_chaps_client_(new chaps::TokenManagerClient()),
      chaps_client_(default_chaps_client_.get()),
      default_pkcs11_init_(new Pkcs11Init()),
      pkcs11_init_(default_pkcs11_init_.get()),
      default_pkcs11_token_factory_(new RealPkcs11TokenFactory()),
      pkcs11_token_factory_(default_pkcs11_token_factory_.get()),
      user_activity_timestamp_manager_(apis.user_activity_timestamp_manager),
      keyset_management_(apis.keyset_management),
      uss_storage_(apis.uss_storage),
      uss_manager_(apis.uss_manager),
      auth_factor_manager_(apis.auth_factor_manager),
      disk_cleanup_threshold_(kFreeSpaceThresholdToTriggerCleanup),
      disk_cleanup_aggressive_threshold_(
          kFreeSpaceThresholdToTriggerAggressiveCleanup),
      disk_cleanup_critical_threshold_(
          kFreeSpaceThresholdToTriggerCriticalCleanup),
      disk_cleanup_target_free_space_(kTargetFreeSpaceAfterCleanup),
      guest_user_(brillo::cryptohome::home::GetGuestUsername()),
      async_init_features_(base::BindRepeating(&UserDataAuth::GetFeatures,
                                               base::Unretained(this))) {}

UserDataAuth::~UserDataAuth() {
  if (low_disk_space_handler_) {
    low_disk_space_handler_->Stop();
  }
  if (mount_thread_) {
    mount_thread_->Stop();
  }
}

bool UserDataAuth::Initialize(scoped_refptr<::dbus::Bus> mount_thread_bus) {
  AssertOnOriginThread();

  // Save the bus object. Note that this doesn't mean that mount_thread_bus_ is
  // not null because the passed in Bus can be (and usually is) null.
  mount_thread_bus_ = std::move(mount_thread_bus);

  // Note that we check to see if |origin_task_runner_| and |mount_task_runner_|
  // are available here because they may have been set to an overridden value
  // during unit testing before Initialize() is called.
  if (!origin_task_runner_) {
    origin_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
  }
  if (!mount_task_runner_) {
    mount_thread_ = std::make_unique<MountThread>(kMountThreadName, this);
    base::Thread::Options options;
    options.message_pump_type = base::MessagePumpType::IO;
    mount_thread_->StartWithOptions(std::move(options));
    mount_task_runner_ = mount_thread_->task_runner();
  }

  crypto_->Init();

  if (!InitializeFilesystemLayout(platform_, &system_salt_)) {
    LOG(ERROR) << "Failed to initialize filesystem layout.";
    return false;
  }

  AsyncInitPtr<SignallingInterface> async_signalling(base::BindRepeating(
      [](UserDataAuth* uda) -> SignallingInterface* {
        if (uda->signalling_intf_ != &uda->default_signalling_) {
          return uda->signalling_intf_;
        }
        return nullptr;
      },
      base::Unretained(this)));
  fingerprint_service_ = std::make_unique<FingerprintAuthBlockService>(
      AsyncInitPtr<FingerprintManager>(base::BindRepeating(
          [](UserDataAuth* uda) {
            uda->AssertOnMountThread();
            return uda->fingerprint_manager_;
          },
          base::Unretained(this))),
      async_signalling);

  AsyncInitPtr<ChallengeCredentialsHelper> async_cc_helper(base::BindRepeating(
      [](UserDataAuth* uda) -> ChallengeCredentialsHelper* {
        uda->AssertOnMountThread();
        if (uda->challenge_credentials_helper_initialized_) {
          return uda->challenge_credentials_helper_;
        }
        return nullptr;
      },
      base::Unretained(this)));
  AsyncInitPtr<BiometricsAuthBlockService> async_biometrics_service(
      base::BindRepeating(
          [](UserDataAuth* uda) {
            uda->AssertOnMountThread();
            return uda->biometrics_service_;
          },
          base::Unretained(this)));
  AsyncInitPtr<RecoverableKeyStoreBackendCertProvider>
      async_key_store_cert_provider(base::BindRepeating(
          [](UserDataAuth* uda) {
            uda->AssertOnMountThread();
            return uda->key_store_cert_provider_;
          },
          base::Unretained(this)));
  if (!auth_block_utility_) {
    default_auth_block_utility_ = std::make_unique<AuthBlockUtilityImpl>(
        keyset_management_, crypto_, platform_, &async_init_features_,
        async_cc_helper, key_challenge_service_factory_,
        async_biometrics_service);
    auth_block_utility_ = default_auth_block_utility_.get();
  }

  if (!auth_factor_driver_manager_) {
    default_auth_factor_driver_manager_ =
        std::make_unique<AuthFactorDriverManager>(
            platform_, crypto_, uss_manager_, async_cc_helper,
            key_challenge_service_factory_, recovery_ab_service_,
            fingerprint_service_.get(), async_biometrics_service);
    auth_factor_driver_manager_ = default_auth_factor_driver_manager_.get();
  }

  if (!fp_migration_utility_) {
    default_fp_migration_utility_ = std::make_unique<FpMigrationUtility>(
        crypto_, async_biometrics_service, &async_init_features_);
    fp_migration_utility_ = default_fp_migration_utility_.get();
  }

  if (!auth_session_manager_) {
    default_auth_session_manager_ = std::make_unique<AuthSessionManager>(
        AuthSession::BackingApis{
            crypto_, platform_, sessions_, keyset_management_,
            auth_block_utility_, auth_factor_driver_manager_,
            auth_factor_manager_, fp_migration_utility_, uss_storage_,
            uss_manager_, &async_init_features_, async_signalling,
            async_key_store_cert_provider},
        mount_task_runner_.get());
    auth_session_manager_ = default_auth_session_manager_.get();
  }

  create_vault_keyset_impl_ = std::make_unique<CreateVaultKeysetRpcImpl>(
      keyset_management_, hwsec_, auth_block_utility_, auth_factor_manager_,
      auth_factor_driver_manager_);

  if (!vault_factory_) {
    auto container_factory =
        std::make_unique<libstorage::StorageContainerFactory>(platform_,
                                                              GetMetrics());
    container_factory->set_allow_fscrypt_v2(fscrypt_v2_);
    default_vault_factory_ = std::make_unique<CryptohomeVaultFactory>(
        platform_, std::move(container_factory));
    default_vault_factory_->set_enable_application_containers(
        enable_application_containers_);
    vault_factory_ = default_vault_factory_.get();

    if (platform_->IsStatefulLogicalVolumeSupported()) {
      base::FilePath stateful_device = platform_->GetStatefulDevice();
      brillo::LogicalVolumeManager* lvm = platform_->GetLogicalVolumeManager();
      brillo::PhysicalVolume pv(stateful_device,
                                std::make_shared<brillo::LvmCommandRunner>());

      std::optional<brillo::VolumeGroup> vg;
      std::optional<brillo::Thinpool> thinpool;

      vg = lvm->GetVolumeGroup(pv);
      if (vg && vg->IsValid()) {
        thinpool = lvm->GetThinpool(*vg, "thinpool");
      }

      if (thinpool && vg) {
        default_vault_factory_->CacheLogicalVolumeObjects(vg, thinpool);
      }
    }
  }

  if (!homedirs_) {
    // This callback runs in HomeDirs::Remove on |this.homedirs_|. Since
    // |this.keyset_management_| won't be destroyed upon call of Remove(),
    // base::Unretained(keyset_management_) will be valid when the callback
    // runs.
    HomeDirs::RemoveCallback remove_callback =
        base::BindRepeating(&KeysetManagement::RemoveLECredentials,
                            base::Unretained(keyset_management_));
    default_homedirs_ = std::make_unique<HomeDirs>(
        platform_, std::make_unique<policy::PolicyProvider>(), remove_callback,
        vault_factory_);
    homedirs_ = default_homedirs_.get();
  }

  auto homedirs = homedirs_->GetHomeDirs();
  for (const auto& dir : homedirs) {
    user_activity_timestamp_manager_->LoadTimestamp(dir.obfuscated);
  }

  if (!mount_factory_) {
    default_mount_factory_ = std::make_unique<MountFactory>();
    mount_factory_ = default_mount_factory_.get();
  }

  if (!user_session_factory_) {
    default_user_session_factory_ = std::make_unique<RealUserSessionFactory>(
        mount_factory_, platform_, homedirs_, user_activity_timestamp_manager_,
        pkcs11_token_factory_);
    user_session_factory_ = default_user_session_factory_.get();
  }

  if (!low_disk_space_handler_) {
    default_low_disk_space_handler_ = std::make_unique<LowDiskSpaceHandler>(
        homedirs_, platform_, async_signalling,
        user_activity_timestamp_manager_);
    low_disk_space_handler_ = default_low_disk_space_handler_.get();
  }
  low_disk_space_handler_->disk_cleanup()->set_cleanup_threshold(
      disk_cleanup_threshold_);
  low_disk_space_handler_->disk_cleanup()->set_aggressive_cleanup_threshold(
      disk_cleanup_aggressive_threshold_);
  low_disk_space_handler_->disk_cleanup()->set_critical_cleanup_threshold(
      disk_cleanup_critical_threshold_);
  low_disk_space_handler_->disk_cleanup()->set_target_free_space(
      disk_cleanup_target_free_space_);

  if (platform_->FileExists(base::FilePath(kNotFirstBootFilePath))) {
    // Clean up any unreferenced mountpoints at startup.
    PostTaskToMountThread(FROM_HERE,
                          base::BindOnce(
                              [](UserDataAuth* userdataauth) {
                                userdataauth->CleanUpStaleMounts(false);
                              },
                              base::Unretained(this)));
  } else {
    platform_->TouchFileDurable(base::FilePath(kNotFirstBootFilePath));
  }

  low_disk_space_handler_->SetUpdateUserActivityTimestampCallback(
      base::BindRepeating(
          base::IgnoreResult(&UserDataAuth::UpdateCurrentUserActivityTimestamp),
          base::Unretained(this), 0));

  hwsec_->RegisterOnReadyCallback(base::BindOnce(
      &UserDataAuth::HwsecReadyCallback, base::Unretained(this)));

  // Create a dbus connection on mount thread.
  PostTaskToMountThread(FROM_HERE,
                        base::BindOnce(&UserDataAuth::CreateMountThreadDBus,
                                       base::Unretained(this)));

  PostTaskToMountThread(FROM_HERE,
                        base::BindOnce(&UserDataAuth::SetDeviceManagementProxy,
                                       base::Unretained(this)));

  // SetDeviceManagementProxy() should be invoked before the following
  // initialization, as low_disk_space_handler_ uses homedirs to check the
  // enterprise_owned status.
  if (!low_disk_space_handler_->Init(base::BindRepeating(
          &UserDataAuth::PostTaskToMountThread, base::Unretained(this))))
    return false;

  PostTaskToMountThread(FROM_HERE,
                        base::BindOnce(&UserDataAuth::CreateFingerprintManager,
                                       base::Unretained(this)));

  PostTaskToMountThread(FROM_HERE,
                        base::BindOnce(&UserDataAuth::CreateBiometricsService,
                                       base::Unretained(this)));

  PostTaskToMountThread(
      FROM_HERE,
      base::BindOnce(
          &UserDataAuth::CreateRecoverableKeyStoreBackendCertProvider,
          base::Unretained(this)));

  PostTaskToMountThread(
      FROM_HERE, base::BindOnce(&UserDataAuth::InitForChallengeResponseAuth,
                                base::Unretained(this)));

  PostTaskToMountThread(FROM_HERE,
                        base::BindOnce(&UserDataAuth::InitializeFeatureLibrary,
                                       base::Unretained(this)));

  return true;
}

void UserDataAuth::CreateMountThreadDBus() {
  AssertOnMountThread();
  if (!mount_thread_bus_) {
    // Setup the D-Bus.
    dbus::Bus::Options options;
    options.bus_type = dbus::Bus::SYSTEM;
    mount_thread_bus_ = base::MakeRefCounted<dbus::Bus>(options);
    CHECK(mount_thread_bus_->Connect())
        << "Failed to connect to system D-Bus on mount thread";
  }
}

CryptohomeStatusOr<UserPolicyFile*> UserDataAuth::LoadUserPolicyFile(
    const ObfuscatedUsername& obfuscated_username) {
  auto [iter, is_new] = user_policy_files_.try_emplace(
      obfuscated_username, platform_, GetUserPolicyPath(obfuscated_username));
  if (is_new && !iter->second.LoadFromFile().ok()) {
    // The file could not be found, so either the policy file doesn't exist, or
    // the file is corrupted and thus could not be read. Regardless, we need to
    // revert to the default settings (which is an empty file).
    iter->second.UpdateUserPolicy(
        SerializedUserPolicy({.auth_factor_type_policy = {}}));
  }
  return &iter->second;
}

void UserDataAuth::ShutdownTask() {
  default_auth_session_manager_.reset();
  default_fingerprint_manager_.reset();
  default_challenge_credentials_helper_.reset();
  if (mount_thread_bus_) {
    mount_thread_bus_->ShutdownAndBlock();
    mount_thread_bus_.reset();
  }
}

void UserDataAuth::InitializeFeatureLibrary() {
  AssertOnMountThread();
  if (!features_) {
    CHECK(feature::PlatformFeatures::Initialize(mount_thread_bus_));
    default_features_ = std::make_unique<Features>(
        mount_thread_bus_, feature::PlatformFeatures::Get());
    features_ = default_features_.get();
    if (!features_) {
      LOG(WARNING) << "Failed to determine USS migration experiment flag";
      return;
    }
  }
}

void UserDataAuth::SetDeviceManagementProxy() {
  AssertOnMountThread();
  if (homedirs_) {
    homedirs_->CreateAndSetDeviceManagementClientProxy(mount_thread_bus_);
  }
  if (!device_management_client_) {
    default_device_management_client_ =
        std::make_unique<DeviceManagementClientProxy>(mount_thread_bus_);
    device_management_client_ = default_device_management_client_.get();
  }
}

Features* UserDataAuth::GetFeatures() {
  return features_;
}

void UserDataAuth::CreateFingerprintManager() {
  AssertOnMountThread();
  if (!fingerprint_manager_) {
    if (!default_fingerprint_manager_) {
      default_fingerprint_manager_ = FingerprintManager::Create(
          mount_thread_bus_,
          dbus::ObjectPath(std::string(biod::kBiodServicePath)
                               .append(kCrosFpBiometricsManagerRelativePath)));
    }
    fingerprint_manager_ = default_fingerprint_manager_.get();
  }
}

void UserDataAuth::CreateBiometricsService() {
  AssertOnMountThread();
  if (!biometrics_service_) {
    if (!default_biometrics_service_) {
      // This will return nullptr if connection to the biod service failed.
      auto bio_proxy = biod::AuthStackManagerProxyBase::Create(
          mount_thread_bus_,
          dbus::ObjectPath(std::string(biod::kBiodServicePath)
                               .append(CrosFpAuthStackManagerRelativePath)));
      if (bio_proxy) {
        auto bio_processor = std::make_unique<BiometricsCommandProcessorImpl>(
            std::move(bio_proxy));
        default_biometrics_service_ =
            std::make_unique<BiometricsAuthBlockService>(
                std::move(bio_processor),
                base::BindRepeating(&UserDataAuth::OnFingerprintEnrollProgress,
                                    base::Unretained(this)),
                base::BindRepeating(&UserDataAuth::OnFingerprintAuthProgress,
                                    base::Unretained(this)));
      }
    }
    biometrics_service_ = default_biometrics_service_.get();
  }
}

void UserDataAuth::OnFingerprintEnrollProgress(
    user_data_auth::AuthEnrollmentProgress result) {
  AssertOnMountThread();
  ReportFingerprintEnrollSignal(result.scan_result().fingerprint_result());
  user_data_auth::PrepareAuthFactorProgress progress;
  user_data_auth::PrepareAuthFactorForAddProgress add_progress;
  add_progress.set_auth_factor_type(
      user_data_auth::AUTH_FACTOR_TYPE_FINGERPRINT);
  *add_progress.mutable_biometrics_progress() = result;
  progress.set_purpose(user_data_auth::PURPOSE_ADD_AUTH_FACTOR);
  *progress.mutable_add_progress() = add_progress;
  signalling_intf_->SendPrepareAuthFactorProgress(progress);
}

void UserDataAuth::OnFingerprintAuthProgress(
    user_data_auth::AuthScanDone result) {
  AssertOnMountThread();
  ReportFingerprintAuthSignal(result.scan_result().fingerprint_result());
  user_data_auth::PrepareAuthFactorProgress progress;
  user_data_auth::PrepareAuthFactorForAuthProgress auth_progress;
  auth_progress.set_auth_factor_type(
      user_data_auth::AUTH_FACTOR_TYPE_FINGERPRINT);
  *auth_progress.mutable_biometrics_progress() = result;
  progress.set_purpose(user_data_auth::PURPOSE_AUTHENTICATE_AUTH_FACTOR);
  *progress.mutable_auth_progress() = auth_progress;
  signalling_intf_->SendPrepareAuthFactorProgress(progress);
}

void UserDataAuth::CreateRecoverableKeyStoreBackendCertProvider() {
  AssertOnMountThread();
  if (!key_store_cert_provider_) {
    if (!default_key_store_cert_provider_) {
      default_key_store_cert_provider_ =
          std::make_unique<RecoverableKeyStoreBackendCertProviderImpl>(
              platform_, std::make_unique<org::chromium::RksAgentProxy>(
                             mount_thread_bus_));
    }
    key_store_cert_provider_ = default_key_store_cert_provider_.get();
  }
}

bool UserDataAuth::PostTaskToOriginThread(const base::Location& from_here,
                                          base::OnceClosure task,
                                          const base::TimeDelta& delay) {
  if (delay.is_zero()) {
    return origin_task_runner_->PostTask(from_here, std::move(task));
  }
  return origin_task_runner_->PostDelayedTask(from_here, std::move(task),
                                              delay);
}

bool UserDataAuth::PostTaskToMountThread(const base::Location& from_here,
                                         base::OnceClosure task,
                                         const base::TimeDelta& delay) {
  CHECK(mount_task_runner_);
  if (delay.is_zero()) {
    // Increase and report the parallel task count.
    parallel_task_count_ += 1;

    // Reduce the parallel task count after finished the task.
    auto full_task = base::BindOnce(
        [](base::OnceClosure task, std::atomic<int>* task_count) {
          std::move(task).Run();
          *task_count -= 1;
        },
        std::move(task), base::Unretained(&parallel_task_count_));

    return mount_task_runner_->PostTask(from_here, std::move(full_task));
  }
  return mount_task_runner_->PostDelayedTask(from_here, std::move(task), delay);
}

bool UserDataAuth::IsMounted(const Username& username, bool* is_ephemeral_out) {
  // Note: This can only run in mount_thread_
  AssertOnMountThread();

  bool is_mounted = false;
  bool is_ephemeral = false;
  if (username->empty()) {
    // No username is specified, so we consider "the cryptohome" to be mounted
    // if any existing cryptohome is mounted.
    for (const auto& [unused, session] : *sessions_) {
      if (session.IsActive()) {
        is_mounted = true;
        is_ephemeral |= session.IsEphemeral();
      }
    }
  } else {
    // A username is specified, check the associated mount object.
    const UserSession* session = sessions_->Find(username);

    if (session) {
      is_mounted = session->IsActive();
      is_ephemeral = is_mounted && session->IsEphemeral();
    }
  }

  if (is_ephemeral_out) {
    *is_ephemeral_out = is_ephemeral;
  }

  return is_mounted;
}

user_data_auth::GetVaultPropertiesReply UserDataAuth::GetVaultProperties(
    user_data_auth::GetVaultPropertiesRequest request) {
  // Note: This can only run in mount_thread_.
  AssertOnMountThread();
  user_data_auth::GetVaultPropertiesReply reply;

  if (request.username().empty()) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUsernameEmpty),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT),
        &reply);
    return reply;
  }

  // A username is specified, find the session.
  const UserSession* session = sessions_->Find(Username(request.username()));
  if (!session) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFound),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT),
        &reply);
    return reply;
  }

  if (!session->IsActive()) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotActivity),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT),
        &reply);
    return reply;
  }

  auto mount_type = MountTypeToVaultEncryptionType(session->GetMountType());
  if (!mount_type.has_value()) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthNoMountFound),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT),
        &reply);
    return reply;
  }

  reply.set_encryption_type(mount_type.value());
  PopulateReplyWithError(OkStatus<CryptohomeError>(), &reply);
  return reply;
}

bool UserDataAuth::RemoveAllMounts() {
  AssertOnMountThread();

  bool success = true;
  while (!sessions_->empty()) {
    const auto& [username, session] = *sessions_->begin();
    if (session.IsActive() && !session.Unmount()) {
      success = false;
    }
    if (!sessions_->Remove(username)) {
      NOTREACHED() << "Failed to remove user session on unmount";
    }
  }
  return success;
}

bool UserDataAuth::FilterActiveMounts(
    std::multimap<const FilePath, const FilePath>* mounts,
    std::multimap<const FilePath, const FilePath>* active_mounts,
    bool include_busy_mount) {
  // Note: This can only run in mount_thread_
  AssertOnMountThread();

  bool skipped = false;
  std::set<const FilePath> children_to_preserve;

  for (auto match = mounts->begin(); match != mounts->end();) {
    // curr->first is the source device of the group that we are processing in
    // this outer loop.
    auto curr = match;
    bool keep = false;

    // Note that we organize the set of mounts with the same source, then
    // process them together. That is, say there's /dev/mmcblk0p1 mounted on
    // /home/user/xxx and /home/chronos/u-xxx/MyFiles/Downloads. They are both
    // from the same source (/dev/mmcblk0p1, or match->first). In this case,
    // we'll decide the fate of all mounts with the same source together. For
    // each such group, the outer loop will run once. The inner loop will
    // iterate through every mount in the group with |match| variable, looking
    // to see if it's owned by any active mounts. If it is, the entire group is
    // kept. Otherwise, (and assuming no open files), the entire group is
    // discarded, as in, not moved into the active_mounts multimap.

    // Walk each set of sources as one group since multimaps are key ordered.
    for (; match != mounts->end() && match->first == curr->first; ++match) {
      // Ignore known mounts.
      for (const auto& [unused, session] : *sessions_) {
        if (session.OwnsMountPoint(match->second)) {
          keep = true;
          // If !include_busy_mount, other mount points not owned scanned after
          // should be preserved as well.
          if (include_busy_mount)
            break;
        }
      }

      // Ignore mounts pointing to children of used mounts.
      if (!include_busy_mount) {
        if (children_to_preserve.find(match->second) !=
            children_to_preserve.end()) {
          keep = true;
          skipped = true;
          LOG(WARNING) << "Stale mount " << match->second.value() << " from "
                       << match->first.value() << " is a just a child.";
        }
      }

      // Optionally, ignore mounts with open files.
      if (!keep && !include_busy_mount) {
        // Mark the mount points that are not in use as 'expired'. Add the mount
        // points to the |active_mounts| list if they are not expired.
        libstorage::ExpireMountResult expire_mount_result =
            platform_->ExpireMount(match->second);
        if (expire_mount_result == libstorage::ExpireMountResult::kBusy) {
          LOG(WARNING) << "Stale mount " << match->second.value() << " from "
                       << match->first.value() << " has active holders.";
          keep = true;
          skipped = true;
        } else if (expire_mount_result ==
                   libstorage::ExpireMountResult::kError) {
          // To avoid unloading any pkcs11 token that is in use, add mount point
          // to the |active_mounts| if it is failed to be expired.
          LOG(ERROR) << "Stale mount " << match->second.value() << " from "
                     << match->first.value()
                     << " failed to be removed from active mounts list.";
          keep = true;
          skipped = true;
        }
      }
    }
    if (keep) {
      std::multimap<const FilePath, const FilePath> children;
      LOG(WARNING) << "Looking for children of " << curr->first;
      platform_->GetMountsBySourcePrefix(curr->first, &children);
      for (const auto& child : children) {
        children_to_preserve.insert(child.second);
      }

      active_mounts->insert(curr, match);
      mounts->erase(curr, match);
    }
  }
  return skipped;
}

void UserDataAuth::GetEphemeralLoopDevicesMounts(
    std::multimap<const FilePath, const FilePath>* mounts) {
  AssertOnMountThread();
  std::multimap<const FilePath, const FilePath> loop_mounts;
  platform_->GetLoopDeviceMounts(&loop_mounts);

  const FilePath sparse_path =
      FilePath(kEphemeralCryptohomeDir).Append(kSparseFileDir);
  for (const auto& device : platform_->GetAttachedLoopDevices()) {
    // Ephemeral mounts are mounts from a loop device with ephemeral sparse
    // backing file.
    if (sparse_path.IsParent(device.backing_file)) {
      auto range = loop_mounts.equal_range(device.device);
      mounts->insert(range.first, range.second);
    }
  }
}

bool UserDataAuth::UnloadPkcs11Tokens(const std::vector<FilePath>& exclude) {
  AssertOnMountThread();

  SecureBlob isolate =
      chaps::IsolateCredentialManager::GetDefaultIsolateCredential();
  std::vector<std::string> tokens;
  if (!chaps_client_->GetTokenList(isolate, &tokens))
    return false;
  for (const std::string& token : tokens) {
    if (token != chaps::kSystemTokenPath && !PrefixPresent(exclude, token)) {
      // It's not a system token and is not under one of the excluded path.
      LOG(INFO) << "Unloading up PKCS #11 token: " << token;
      chaps_client_->UnloadToken(isolate, FilePath(token));
    }
  }
  return true;
}

bool UserDataAuth::CleanUpStaleMounts(bool force) {
  AssertOnMountThread();

  // This function is meant to aid in a clean recovery from a crashed or
  // manually restarted cryptohomed.  Cryptohomed may restart:
  // 1. Before any mounts occur
  // 2. While mounts are active
  // 3. During an unmount
  // In case #1, there should be no special work to be done.
  // The best way to disambiguate #2 and #3 is to determine if there are
  // any active open files on any stale mounts.  If there are open files,
  // then we've likely(*) resumed an active session. If there are not,
  // the last cryptohome should have been unmounted.
  // It's worth noting that a restart during active use doesn't impair
  // other user session behavior, like CheckKey, because it doesn't rely
  // exclusively on mount state.
  //
  // In the future, it may make sense to attempt to keep the MountMap
  // persisted to disk which would make resumption much easier.
  //
  // (*) Relies on the expectation that all processes have been killed off.

  // TODO(b:225769250, dlunev): figure out cleanup for non-mounted application
  // containers.

  // Stale shadow and ephemeral mounts.
  std::multimap<const FilePath, const FilePath> shadow_mounts;
  std::multimap<const FilePath, const FilePath> ephemeral_mounts;
  std::multimap<const FilePath, const FilePath> dmcrypt_mounts,
      grouped_dmcrypt_mounts;

  // Active mounts that we don't intend to unmount.
  std::multimap<const FilePath, const FilePath> active_mounts;

  // Retrieve all the mounts that's currently mounted by the kernel and concerns
  // us
  platform_->GetMountsBySourcePrefix(ShadowRoot(), &shadow_mounts);
  platform_->GetMountsByDevicePrefix(kDeviceMapperDevicePrefix,
                                     &dmcrypt_mounts);
  GroupDmcryptDeviceMounts(&dmcrypt_mounts, &grouped_dmcrypt_mounts);
  GetEphemeralLoopDevicesMounts(&ephemeral_mounts);

  // Remove mounts that we've a record of or have open files on them
  bool skipped =
      FilterActiveMounts(&shadow_mounts, &active_mounts, force) ||
      FilterActiveMounts(&ephemeral_mounts, &active_mounts, force) ||
      FilterActiveMounts(&grouped_dmcrypt_mounts, &active_mounts, force);

  // Unload PKCS#11 tokens on any mount that we're going to unmount.
  std::vector<FilePath> excluded_mount_points;
  for (const auto& mount : active_mounts) {
    excluded_mount_points.push_back(mount.second);
  }
  UnloadPkcs11Tokens(excluded_mount_points);

  // Unmount anything left.
  for (const auto& match : grouped_dmcrypt_mounts) {
    LOG(WARNING) << "Lazily unmounting stale dmcrypt mount: "
                 << match.second.value() << " for " << match.first.value();
    // true for lazy unmount, nullptr for us not needing to know if it's really
    // unmounted.
    platform_->Unmount(match.second, true, nullptr);
  }

  for (const auto& match : shadow_mounts) {
    LOG(WARNING) << "Lazily unmounting stale shadow mount: "
                 << match.second.value() << " from " << match.first.value();
    // true for lazy unmount, nullptr for us not needing to know if it's really
    // unmounted.
    platform_->Unmount(match.second, true, nullptr);
  }

  // Attempt to clear the encryption key for the shadow directories once
  // the mount has been unmounted. The encryption key needs to be cleared
  // after all the unmounts are done to ensure that none of the existing
  // submounts becomes inaccessible.
  if (force && !shadow_mounts.empty()) {
    // Attempt to clear fscrypt encryption keys for the shadow mounts.
    for (const auto& match : shadow_mounts) {
      if (!platform_->InvalidateDirCryptoKey(dircrypto::KeyReference(),
                                             match.first)) {
        LOG(WARNING) << "Failed to clear fscrypt keys for stale mount: "
                     << match.first;
      }
    }

    // Clear all keys in the user keyring for ecryptfs mounts.
    if (!platform_->ClearUserKeyring()) {
      LOG(WARNING) << "Failed to clear stale user keys.";
    }
  }
  for (const auto& match : ephemeral_mounts) {
    LOG(WARNING) << "Lazily unmounting stale ephemeral mount: "
                 << match.second.value() << " from " << match.first.value();
    // true for lazy unmount, nullptr for us not needing to know if it's really
    // unmounted.
    platform_->Unmount(match.second, true, nullptr);
    // Clean up destination directory for ephemeral mounts under ephemeral
    // cryptohome dir.
    if (base::StartsWith(match.first.value(), libstorage::kLoopPrefix,
                         base::CompareCase::SENSITIVE) &&
        FilePath(kEphemeralCryptohomeDir).IsParent(match.second)) {
      platform_->DeletePathRecursively(match.second);
    }
  }

  // Clean up all stale sparse files, this is comprised of two stages:
  // 1. Clean up stale loop devices.
  // 2. Clean up stale sparse files.
  // Note that some mounts are backed by loop devices, and loop devices are
  // backed by sparse files.

  std::vector<libstorage::Platform::LoopDevice> loop_devices =
      platform_->GetAttachedLoopDevices();
  const FilePath sparse_dir =
      FilePath(kEphemeralCryptohomeDir).Append(kSparseFileDir);
  std::vector<FilePath> stale_sparse_files;
  platform_->EnumerateDirectoryEntries(sparse_dir, false /* is_recursive */,
                                       &stale_sparse_files);

  // We'll go through all loop devices, and for every of them, we'll see if we
  // can remove it. Also in the process, we'll get to keep track of which sparse
  // files are actually used by active loop devices.
  for (const auto& device : loop_devices) {
    // Check whether the loop device is created from an ephemeral sparse file.
    if (!sparse_dir.IsParent(device.backing_file)) {
      // Nah, it's this loop device is not backed by an ephemeral sparse file
      // created by cryptohome, so we'll leave it alone.
      continue;
    }

    // Check if any of our active mounts are backed by this loop device.
    if (active_mounts.count(device.device) == 0) {
      // Nope, this loop device have nothing to do with our active mounts.
      LOG(WARNING) << "Detaching stale loop device: " << device.device.value();
      if (!platform_->DetachLoop(device.device)) {
        PLOG(ERROR) << "Can't detach stale loop: " << device.device.value();
        ReportCryptohomeError(kEphemeralCleanUpFailed);
      }
    } else {
      // This loop device backs one of our active_mounts, so we can't count it
      // as stale. Thus removing from the stale_sparse_files list.
      stale_sparse_files.erase(
          std::remove(stale_sparse_files.begin(), stale_sparse_files.end(),
                      device.backing_file),
          stale_sparse_files.end());
    }
  }

  // Now we clean up the stale sparse files.
  for (const auto& file : stale_sparse_files) {
    LOG(WARNING) << "Deleting stale ephemeral backing sparse file: "
                 << file.value();
    if (!platform_->DeleteFile(file)) {
      PLOG(ERROR) << "Failed to clean up ephemeral sparse file: "
                  << file.value();
      ReportCryptohomeError(kEphemeralCleanUpFailed);
    }
  }

  return skipped;
}

user_data_auth::UnmountReply UserDataAuth::Unmount() {
  AssertOnMountThread();

  bool unmount_ok = RemoveAllMounts();

  // If there are any unexpected mounts lingering from a crash/restart,
  // clean them up now.
  // Note that we do not care about the return value of CleanUpStaleMounts()
  // because it doesn't matter if any mount is skipped due to open files, and
  // additionally, since we've specified force=true, it'll not skip over mounts
  // with open files.
  CleanUpStaleMounts(true);

  // Removes all ephemeral cryptohomes owned by anyone other than the owner
  // user (if set) and non ephemeral users, regardless of free disk space.
  homedirs_->RemoveCryptohomesBasedOnPolicy();

  // Since all the user mounts are now gone, there should not be any active
  // authsessions left. Remove them all and discard any loaded state related to
  // them such as loaded USS data.
  CryptohomeStatus result = TerminateAuthSessionsAndClearLoadedState();

  // If the unmount failed, reporting the error there takes priority over the
  // failed termination of auth sessions.
  if (!unmount_ok) {
    result = MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthRemoveAllMountsFailedInUnmount),
        ErrorActionSet({PossibleAction::kReboot}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_MOUNT_FATAL);
  }

  user_data_auth::UnmountReply reply;
  PopulateReplyWithError(result, &reply);
  return reply;
}

void UserDataAuth::InitializePkcs11(UserSession* session) {
  AssertOnMountThread();

  // We should not pass nullptr to this method.
  CHECK(session);

  bool still_mounted = false;

  // The mount has to be mounted, that is, still tracked by cryptohome.
  // Otherwise there's no point in initializing PKCS#11 for it. The reason for
  // this check is because it might be possible for Unmount() to be called after
  // mounting and before getting here.
  for (const auto& [unused, user_session] : *sessions_) {
    if (&user_session == session && session->IsActive()) {
      still_mounted = true;
      break;
    }
  }

  if (!still_mounted) {
    LOG(WARNING)
        << "PKCS#11 initialization requested but cryptohome is not mounted.";
    return;
  }

  // Note that the timer stops in the Mount class' method.
  ReportTimerStart(kPkcs11InitTimer);

  if (session->GetPkcs11Token()) {
    session->GetPkcs11Token()->Insert();
  }

  ReportTimerStop(kPkcs11InitTimer);

  LOG(INFO) << "PKCS#11 initialization succeeded.";
}

void UserDataAuth::Pkcs11RestoreTpmTokens() {
  AssertOnMountThread();

  for (const auto& [unused, session] : *sessions_) {
    if (session.IsActive()) {
      session.GetPkcs11Token()->TryRestoring();
    }
  }
}

void UserDataAuth::EnsureCryptohomeKeys() {
  if (!IsOnMountThread()) {
    // We are not on mount thread, but to be safe, we'll only access Mount
    // objects on mount thread, so let's post ourself there.
    PostTaskToMountThread(FROM_HERE,
                          base::BindOnce(&UserDataAuth::EnsureCryptohomeKeys,
                                         base::Unretained(this)));
    return;
  }

  AssertOnMountThread();

  if (!cryptohome_keys_manager_->HasAnyCryptohomeKey()) {
    cryptohome_keys_manager_->Init();
  }
}

void UserDataAuth::set_cleanup_threshold(uint64_t cleanup_threshold) {
  disk_cleanup_threshold_ = cleanup_threshold;
}

void UserDataAuth::set_aggressive_cleanup_threshold(
    uint64_t aggressive_cleanup_threshold) {
  disk_cleanup_aggressive_threshold_ = aggressive_cleanup_threshold;
}

void UserDataAuth::set_critical_cleanup_threshold(
    uint64_t critical_cleanup_threshold) {
  disk_cleanup_critical_threshold_ = critical_cleanup_threshold;
}

void UserDataAuth::set_target_free_space(uint64_t target_free_space) {
  disk_cleanup_target_free_space_ = target_free_space;
}

void UserDataAuth::SetSignallingInterface(SignallingInterface& signalling) {
  signalling_intf_ = &signalling;
}

void UserDataAuth::HwsecReadyCallback(hwsec::Status status) {
  if (!IsOnMountThread()) {
    // We are not on mount thread, so let's post ourself there.
    PostTaskToMountThread(
        FROM_HERE, base::BindOnce(&UserDataAuth::HwsecReadyCallback,
                                  base::Unretained(this), std::move(status)));
    return;
  }

  AssertOnMountThread();

  if (!status.ok()) {
    LOG(ERROR) << "HwsecReadyCallback failed: " << status;
    return;
  }

  // Make sure cryptohome keys are loaded and ready for every mount.
  EnsureCryptohomeKeys();
}

void UserDataAuth::EnsureBootLockboxFinalized() {
  AssertOnMountThread();

  // Lock NVRamBootLockbox
  auto nvram_boot_lockbox_client =
      bootlockbox::BootLockboxClient::CreateBootLockboxClient();
  if (!nvram_boot_lockbox_client) {
    LOG(WARNING) << "Failed to create nvram_boot_lockbox_client";
    return;
  }

  if (!nvram_boot_lockbox_client->Finalize()) {
    LOG(WARNING) << "Failed to finalize nvram lockbox.";
  }
}

void UserDataAuth::BlockPkEstablishment() {
  AssertOnMountThread();

  if (pk_establishment_blocked_) {
    return;
  }

  hwsec::StatusOr<bool> enabled = hwsec_pw_manager_->IsEnabled();
  if (!enabled.ok() || !*enabled) {
    return;
  }

  // Pk related mechanisms are only added in PW version 2.
  hwsec::StatusOr<uint8_t> version = hwsec_pw_manager_->GetVersion();
  if (!version.ok() || *version <= 1) {
    return;
  }

  hwsec::Status status = hwsec_pw_manager_->BlockGeneratePk();
  if (!status.ok()) {
    LOG(WARNING) << "Block biometrics Pk establishment failed: "
                 << status.status();
  } else {
    pk_establishment_blocked_ = true;
    if (!platform_->FileExists(
            base::FilePath(kPinweaverPkEstablishmentBlocked))) {
      platform_->TouchFileDurable(
          base::FilePath(kPinweaverPkEstablishmentBlocked));
    }
  }
}

UserSession* UserDataAuth::GetOrCreateUserSession(const Username& username) {
  // This method touches the |sessions_| object so it needs to run on
  // |mount_thread_|
  AssertOnMountThread();
  UserSession* session = sessions_->Find(username);
  if (!session) {
    // Lock bootlockbox as we considered the device becoming more vulnerable to
    // attackers.
    EnsureBootLockboxFinalized();
    // Block biometrics pairing key establishment afterwards as we considered
    // the device becoming more vulnerable to attackers.
    BlockPkEstablishment();
    // We don't have a mount associated with |username|, let's create one.
    std::unique_ptr<UserSession> owned_session = user_session_factory_->New(
        username, legacy_mount_, bind_mount_downloads_);
    session = owned_session.get();
    if (!sessions_->Add(username, std::move(owned_session))) {
      NOTREACHED() << "Failed to add created user session";
      return nullptr;
    }
  }
  return session;
}

void UserDataAuth::RemoveInactiveUserSession(const Username& username) {
  AssertOnMountThread();

  UserSession* session = sessions_->Find(username);
  if (!session || session->IsActive()) {
    return;
  }

  if (!sessions_->Remove(username)) {
    NOTREACHED() << "Failed to remove inactive user session.";
  }
}

void UserDataAuth::InitForChallengeResponseAuth() {
  AssertOnMountThread();
  if (challenge_credentials_helper_initialized_) {
    // Already successfully initialized.
    return;
  }

  if (!challenge_credentials_helper_) {
    // Lazily create the helper object that manages generation/decryption of
    // credentials for challenge-protected vaults.
    default_challenge_credentials_helper_ =
        std::make_unique<ChallengeCredentialsHelperImpl>(hwsec_);
    challenge_credentials_helper_ = default_challenge_credentials_helper_.get();
  }

  if (!mount_thread_bus_) {
    LOG(ERROR) << "Cannot do challenge-response mount without system D-Bus bus";
    return;
  }
  key_challenge_service_factory_->SetMountThreadBus(mount_thread_bus_);

  challenge_credentials_helper_initialized_ = true;
}

void UserDataAuth::Remove(user_data_auth::RemoveRequest request,
                          OnDoneCallback<user_data_auth::RemoveReply> on_done) {
  AssertOnMountThread();

  if (!request.has_identifier() && request.auth_session_id().empty()) {
    // RemoveRequest must have identifier or an AuthSession Id
    ReplyWithError(
        std::move(on_done), {},
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthNoIDInRemove),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }

  // If the caller supplies an account identifier then we need to start a new
  // session to do the cleanup.
  if (request.auth_session_id().empty()) {
    base::UnguessableToken token = auth_session_manager_->CreateAuthSession(
        GetAccountId(request.identifier()),
        {.is_ephemeral_user = false, .intent = AuthIntent::kDecrypt});
    // Rewrite the request to use the new session ID and not the account ID.
    request.clear_identifier();
    request.set_auth_session_id(
        AuthSession::GetSerializedStringFromToken(token));
  }

  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInRemove),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::RemoveWithSession, base::Unretained(this)));
}

void UserDataAuth::RemoveWithSession(
    user_data_auth::RemoveRequest request,
    OnDoneCallback<user_data_auth::RemoveReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::RemoveReply reply;

  Username account_id = auth_session->username();
  if (account_id->empty()) {
    // RemoveRequest must have valid account_id.
    ReplyWithError(std::move(on_done), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(
                           kLocUserDataAuthNoAccountIdWithAuthSessionInRemove),
                       ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                                       PossibleAction::kReboot}),
                       user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }

  ObfuscatedUsername obfuscated = SanitizeUserName(account_id);

  const UserSession* const session = sessions_->Find(account_id);
  if (session && session->IsActive()) {
    // Can't remove active user
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUserActiveInRemove),
            ErrorActionSet({PossibleAction::kReboot}),
            user_data_auth::CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY));
    return;
  }

  AuthSession* auth_session_ptr = auth_session.Get();
  auth_session_ptr->PrepareUserForRemoval(base::BindOnce(
      &UserDataAuth::OnPreparedUserForRemoval, base::Unretained(this),
      obfuscated, std::move(auth_session).BindForCallback(),
      std::move(on_done)));
}

void UserDataAuth::OnPreparedUserForRemoval(
    const ObfuscatedUsername& obfuscated,
    InUseAuthSession auth_session,
    base::OnceCallback<void(const user_data_auth::RemoveReply&)> on_done) {
  user_data_auth::RemoveReply reply;
  if (!homedirs_->Remove(obfuscated)) {
    // User vault removal failed.
    ReplyWithError(std::move(on_done), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(kLocUserDataAuthRemoveFailedInRemove),
                       ErrorActionSet({PossibleAction::kPowerwash,
                                       PossibleAction::kReboot}),
                       user_data_auth::CRYPTOHOME_ERROR_REMOVE_FAILED));
    return;
  }

  // Since the user is now removed, any further operations require a fresh
  // AuthSession. So terminate ALL auth sessions for the user.
  auth_session_manager_->RemoveUserAuthSessions(obfuscated);
  std::move(auth_session).Release();

  // Send RemoveCompleted signal.
  user_data_auth::RemoveCompleted signal;
  signal.set_sanitized_username(*obfuscated);
  signalling_intf_->SendRemoveCompleted(signal);

  // We should have removed the auth sessions of the user-to-be-removed. Try
  // to unload the encrypted USS from manager otherwise the same account can't
  // be added again. If the unload failed, the same account can't be added again
  // until the next boot.
  CryptohomeStatus status = uss_manager_->DiscardEncrypted(obfuscated);
  if (!status.ok()) {
    LOG(WARNING) << "Failed to discard encrypted USS: " << status;
  }

  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

user_data_auth::ResetApplicationContainerReply
UserDataAuth::ResetApplicationContainer(
    const user_data_auth::ResetApplicationContainerRequest& request) {
  AssertOnMountThread();
  user_data_auth::ResetApplicationContainerReply reply;
  Username account_id = GetAccountId(request.account_id());

  if (account_id->empty() || request.application_name().empty()) {
    // RemoveRequest must have identifier or an AuthSession Id
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthNoIDInResetAppContainer),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT),
        &reply);
    return reply;
  }

  UserSession* session = sessions_->Find(account_id);
  if (!session || !session->IsActive()) {
    // Can't reset container of inactive user.
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUserInactiveInResetAppContainer),
            ErrorActionSet({PossibleAction::kReboot}),
            user_data_auth::CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY),
        &reply);
    return reply;
  }

  if (!session->ResetApplicationContainer(request.application_name())) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUserFailedResetAppContainer),
            ErrorActionSet({PossibleAction::kReboot}),
            user_data_auth::CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY),
        &reply);
    return reply;
  }

  PopulateReplyWithError(OkStatus<CryptohomeError>(), &reply);
  return reply;
}

void UserDataAuth::StartMigrateToDircrypto(
    user_data_auth::StartMigrateToDircryptoRequest request,
    OnDoneCallback<user_data_auth::StartMigrateToDircryptoReply> on_done,
    Mount::MigrationCallback progress_callback) {
  AssertOnMountThread();

  // If the request does not specify an auth session then just directly execute
  // using the specified username.
  if (request.auth_session_id().empty()) {
    Username username = GetAccountId(request.account_id());
    StartMigrateToDircryptoWithUsername(std::move(request), std::move(on_done),
                                        std::move(progress_callback),
                                        std::move(username));
    return;
  }

  // Schedule the request to run with the username associated with the specified
  // auth session once that session is available to run.
  std::string auth_session_id = request.auth_session_id();
  auth_session_manager_->RunWhenAvailable(
      auth_session_id,
      base::BindOnce(
          [](user_data_auth::StartMigrateToDircryptoRequest request,
             OnDoneCallback<user_data_auth::StartMigrateToDircryptoReply>
                 on_done,
             Mount::MigrationCallback progress_callback, UserDataAuth* this_uda,
             InUseAuthSession auth_session) {
            CryptohomeStatus status = auth_session.AuthSessionStatus();
            if (!status.ok()) {
              LOG(ERROR) << "StartMigrateToDircrypto: Invalid auth_session_id.";
              user_data_auth::DircryptoMigrationProgress progress;
              progress.set_status(user_data_auth::DIRCRYPTO_MIGRATION_FAILED);
              progress_callback.Run(progress);
              // Note that we still reply with "ok" because failures are
              // reported via the progress callback.
              ReplyWithError(std::move(on_done),
                             user_data_auth::StartMigrateToDircryptoReply{},
                             OkStatus<CryptohomeError>());
              return;
            }
            this_uda->StartMigrateToDircryptoWithUsername(
                std::move(request), std::move(on_done),
                std::move(progress_callback), auth_session->username());
          },
          std::move(request), std::move(on_done), std::move(progress_callback),
          this));
}

void UserDataAuth::StartMigrateToDircryptoWithUsername(
    user_data_auth::StartMigrateToDircryptoRequest request,
    OnDoneCallback<user_data_auth::StartMigrateToDircryptoReply> on_done,
    Mount::MigrationCallback progress_callback,
    Username username) {
  MigrationType migration_type = request.minimal_migration()
                                     ? MigrationType::MINIMAL
                                     : MigrationType::FULL;
  user_data_auth::StartMigrateToDircryptoReply reply;
  user_data_auth::DircryptoMigrationProgress progress;

  // Note that total_bytes and current_bytes field in |progress| is discarded by
  // client whenever |progress.status| is not DIRCRYPTO_MIGRATION_IN_PROGRESS,
  // this is why they are left with the default value of 0 here.
  UserSession* const session = sessions_->Find(username);
  if (!session) {
    LOG(ERROR) << "StartMigrateToDircrypto: Failed to get session.";
    progress.set_status(user_data_auth::DIRCRYPTO_MIGRATION_FAILED);
    progress_callback.Run(progress);
    ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
    return;
  }
  LOG(INFO) << "StartMigrateToDircrypto: Migrating to dircrypto.";
  if (!session->MigrateVault(progress_callback, migration_type)) {
    LOG(ERROR) << "StartMigrateToDircrypto: Failed to migrate.";
    progress.set_status(user_data_auth::DIRCRYPTO_MIGRATION_FAILED);
    progress_callback.Run(progress);
    ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
    return;
  }
  LOG(INFO) << "StartMigrateToDircrypto: Migration done.";
  progress.set_status(user_data_auth::DIRCRYPTO_MIGRATION_SUCCESS);
  progress_callback.Run(progress);
  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

user_data_auth::CryptohomeErrorCode UserDataAuth::NeedsDircryptoMigration(
    const AccountIdentifier& account, bool* result) {
  AssertOnMountThread();
  ObfuscatedUsername obfuscated_username =
      SanitizeUserName(GetAccountId(account));
  if (!homedirs_->Exists(obfuscated_username)) {
    LOG(ERROR) << "Unknown user in NeedsDircryptoMigration.";
    return user_data_auth::CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND;
  }

  *result = !force_ecryptfs_ &&
            homedirs_->NeedsDircryptoMigration(obfuscated_username);
  return user_data_auth::CRYPTOHOME_ERROR_NOT_SET;
}

bool UserDataAuth::IsLowEntropyCredentialSupported() {
  AssertOnOriginThread();
  hwsec::StatusOr<bool> is_enabled = hwsec_->IsPinWeaverEnabled();
  if (!is_enabled.ok()) {
    LOG(ERROR) << "Failed to get pinweaver status";
    return false;
  }
  return is_enabled.value();
}

int64_t UserDataAuth::GetAccountDiskUsage(const AccountIdentifier& account) {
  AssertOnMountThread();
  // Note that if the given |account| is invalid or non-existent, then HomeDirs'
  // implementation of ComputeDiskUsage is specified to return 0.
  return homedirs_->ComputeDiskUsage(SanitizeUserName(GetAccountId(account)));
}

bool UserDataAuth::Pkcs11IsTpmTokenReady() {
  AssertOnMountThread();
  // We touched the sessions_ object, so we need to be on mount thread.

  for (const auto& [unused, session] : *sessions_) {
    if (!session.GetPkcs11Token() || !session.GetPkcs11Token()->IsReady()) {
      return false;
    }
  }

  return true;
}

user_data_auth::TpmTokenInfo UserDataAuth::Pkcs11GetTpmTokenInfo(
    const Username& username) {
  AssertOnOriginThread();
  user_data_auth::TpmTokenInfo result;
  std::string label, pin;
  CK_SLOT_ID slot;
  FilePath token_path;
  if (username->empty()) {
    // We want to get the system token.

    // Get the label and pin for system token.
    pkcs11_init_->GetTpmTokenInfo(&label, &pin);

    token_path = FilePath(chaps::kSystemTokenPath);
  } else {
    // We want to get the user token.

    // Get the label and pin for user token.
    pkcs11_init_->GetTpmTokenInfoForUser(username, &label, &pin);

    token_path = homedirs_->GetChapsTokenDir(SanitizeUserName(username));
  }

  result.set_label(label);
  result.set_user_pin(pin);

  if (!pkcs11_init_->GetTpmTokenSlotForPath(token_path, &slot)) {
    // Failed to get the slot, let's use -1 for default.
    slot = -1;
  }
  result.set_slot(slot);

  return result;
}

void UserDataAuth::Pkcs11Terminate() {
  AssertOnMountThread();
  // We are touching the |sessions_| object so we need to be on mount thread.

  for (const auto& [unused, session] : *sessions_) {
    if (session.GetPkcs11Token()) {
      session.GetPkcs11Token()->Remove();
    }
  }
}

user_data_auth::GetWebAuthnSecretReply UserDataAuth::GetWebAuthnSecret(
    const user_data_auth::GetWebAuthnSecretRequest& request) {
  AssertOnMountThread();
  user_data_auth::GetWebAuthnSecretReply reply;

  if (!request.has_account_id()) {
    LOG(ERROR) << "GetWebAuthnSecretRequest must have account_id.";
    reply.set_error(user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    return reply;
  }

  Username account_id = GetAccountId(request.account_id());
  if (account_id->empty()) {
    LOG(ERROR) << "GetWebAuthnSecretRequest must have valid account_id.";
    reply.set_error(user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    return reply;
  }

  UserSession* const session = sessions_->Find(account_id);
  std::unique_ptr<brillo::SecureBlob> secret;
  if (session) {
    secret = session->GetWebAuthnSecret();
  }
  if (!secret) {
    LOG(ERROR) << "Failed to get WebAuthn secret.";
    reply.set_error(user_data_auth::CRYPTOHOME_ERROR_KEY_NOT_FOUND);
    return reply;
  }

  reply.set_webauthn_secret(secret->to_string());
  return reply;
}

user_data_auth::GetWebAuthnSecretHashReply UserDataAuth::GetWebAuthnSecretHash(
    const user_data_auth::GetWebAuthnSecretHashRequest& request) {
  AssertOnMountThread();
  user_data_auth::GetWebAuthnSecretHashReply reply;

  if (!request.has_account_id()) {
    LOG(ERROR) << "GetWebAuthnSecretHashRequest must have account_id.";
    reply.set_error(user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    return reply;
  }

  Username account_id = GetAccountId(request.account_id());
  if (account_id->empty()) {
    LOG(ERROR) << "GetWebAuthnSecretHashRequest must have valid account_id.";
    reply.set_error(user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    return reply;
  }

  const UserSession* const session = sessions_->Find(account_id);
  brillo::SecureBlob secret_hash;
  if (session) {
    secret_hash = session->GetWebAuthnSecretHash();
  }
  if (secret_hash.empty()) {
    LOG(ERROR) << "Failed to get WebAuthn secret hash.";
    reply.set_error(user_data_auth::CRYPTOHOME_ERROR_KEY_NOT_FOUND);
    return reply;
  }

  reply.set_webauthn_secret_hash(secret_hash.to_string());
  return reply;
}

void UserDataAuth::GetRecoverableKeyStores(
    user_data_auth::GetRecoverableKeyStoresRequest request,
    OnDoneCallback<user_data_auth::GetRecoverableKeyStoresReply> on_done) {
  AssertOnMountThread();
  user_data_auth::GetRecoverableKeyStoresReply reply;

  // Check whether user exists.
  // Compute the raw and sanitized user name from the request.
  Username username = GetAccountId(request.account_id());
  ObfuscatedUsername obfuscated_username = SanitizeUserName(username);
  UserSession* user_session = sessions_->Find(username);  // May be null!
  bool is_persistent_user =
      (user_session && !user_session->IsEphemeral()) ||
      platform_->DirectoryExists(UserPath(obfuscated_username));
  bool is_ephemeral_user = user_session && user_session->IsEphemeral();
  if (!is_persistent_user && !is_ephemeral_user) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthUserNonexistentInGetRecoverableKeyStores),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }
  // Ephemeral users don't have AuthBlockStates, so they'll never have
  // recoverable key stores generated.
  if (!is_persistent_user) {
    ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
    return;
  }

  // Load the AuthFactorMap.
  AuthFactorMap& auth_factor_map =
      auth_factor_manager_->GetAuthFactorMap(obfuscated_username);

  // Populate the response from the items in the AuthFactorMap.
  for (AuthFactorMap::ValueView item : auth_factor_map) {
    const AuthBlockState& state = item.auth_factor().auth_block_state();
    if (!state.recoverable_key_store_state.has_value()) {
      continue;
    }
    RecoverableKeyStore key_store;
    if (!key_store.ParseFromString(brillo::BlobToString(
            state.recoverable_key_store_state->key_store_proto))) {
      LOG(WARNING) << "Failed to parse recoverable key store proto from auth "
                      "block state.";
      continue;
    }
    *reply.add_key_stores() = std::move(key_store);
  }
  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

const brillo::SecureBlob& UserDataAuth::GetSystemSalt() {
  AssertOnOriginThread();
  CHECK_NE(system_salt_.size(), 0)
      << "Cannot call GetSystemSalt before initialization";
  return system_salt_;
}

bool UserDataAuth::UpdateCurrentUserActivityTimestamp(int time_shift_sec) {
  AssertOnMountThread();
  // We are touching the sessions object, so we'll need to be on mount thread.

  bool success = true;
  for (const auto& [username, session] : *sessions_) {
    const ObfuscatedUsername obfuscated_username = SanitizeUserName(username);
    // Inactive session is not current and ephemerals should not have ts since
    // they do not affect disk space use and do not participate in disk
    // cleaning.
    if (!session.IsActive() || session.IsEphemeral()) {
      continue;
    }
    success &= user_activity_timestamp_manager_->UpdateTimestamp(
        obfuscated_username, base::Seconds(time_shift_sec));
  }

  return success;
}

bool UserDataAuth::GetRsuDeviceId(std::string* rsu_device_id) {
  AssertOnOriginThread();

  hwsec::StatusOr<brillo::Blob> rsu = hwsec_->GetRsuDeviceId();
  if (!rsu.ok()) {
    LOG(INFO) << "Failed to get RSU device ID: " << rsu.status();
    return false;
  }

  *rsu_device_id = brillo::BlobToString(rsu.value());
  return true;
}

bool UserDataAuth::RequiresPowerwash() {
  AssertOnOriginThread();
  const bool is_powerwash_required = !crypto_->CanUnsealWithUserAuth();
  return is_powerwash_required;
}

user_data_auth::CryptohomeErrorCode
UserDataAuth::LockToSingleUserMountUntilReboot(
    const AccountIdentifier& account_id) {
  AssertOnOriginThread();
  const ObfuscatedUsername obfuscated_username =
      SanitizeUserName(GetAccountId(account_id));

  homedirs_->SetLockedToSingleUser();
  brillo::Blob pcr_value;

  hwsec::StatusOr<bool> is_current_user_set = hwsec_->IsCurrentUserSet();
  if (!is_current_user_set.ok()) {
    LOG(ERROR) << "Failed to get current user status for "
                  "LockToSingleUserMountUntilReboot(): "
               << is_current_user_set.status();
    return user_data_auth::CRYPTOHOME_ERROR_FAILED_TO_READ_PCR;
  }

  if (is_current_user_set.value()) {
    return user_data_auth::CRYPTOHOME_ERROR_PCR_ALREADY_EXTENDED;
  }

  if (hwsec::Status status = hwsec_->SetCurrentUser(*obfuscated_username);
      !status.ok()) {
    LOG(ERROR)
        << "Failed to set current user for LockToSingleUserMountUntilReboot(): "
        << status;
    return user_data_auth::CRYPTOHOME_ERROR_FAILED_TO_EXTEND_PCR;
  }

  return user_data_auth::CRYPTOHOME_ERROR_NOT_SET;
}

user_data_auth::GetPinWeaverInfoReply UserDataAuth::GetPinWeaverInfo() {
  user_data_auth::GetPinWeaverInfoReply reply;

  hwsec::StatusOr<bool> enabled = hwsec_pw_manager_->IsEnabled();
  if (!enabled.ok()) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthGetPinWeaverInfoIsEnabledFailed),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_BACKING_STORE_FAILURE),
        &reply);
    return reply;
  }
  if (!*enabled) {
    PopulateReplyWithError(OkStatus<CryptohomeError>(), &reply);
    reply.set_has_credential(false);
    return reply;
  }

  hwsec::StatusOr<bool> has_cred = hwsec_pw_manager_->HasAnyCredential();
  if (!has_cred.ok()) {
    PopulateReplyWithError(
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthGetPinWeaverInfoCheckFailed),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_BACKING_STORE_FAILURE),
        &reply);
    return reply;
  }
  reply.set_has_credential(*has_cred);

  PopulateReplyWithError(OkStatus<CryptohomeError>(), &reply);
  return reply;
}

bool UserDataAuth::OwnerUserExists() {
  AssertOnOriginThread();
  ObfuscatedUsername owner;
  return homedirs_->GetOwner(&owner);
}

bool UserDataAuth::IsArcQuotaSupported() {
  AssertOnOriginThread();
  // Quota is not supported if there are one or more unmounted Android users.
  // (b/181159107)
  return homedirs_->GetUnmountedAndroidDataCount() == 0;
}

void UserDataAuth::StartAuthSession(
    user_data_auth::StartAuthSessionRequest request,
    OnDoneCallback<user_data_auth::StartAuthSessionReply> on_done) {
  AssertOnMountThread();
  user_data_auth::StartAuthSessionReply reply;

  // Determine if the request is for an ephemeral user.
  bool is_ephemeral_user = request.is_ephemeral_user();

  if (request.intent() == user_data_auth::AUTH_INTENT_UNSPECIFIED) {
    // TODO(b/240596931): Stop allowing the UNSPECIFIED value after Chrome's
    // change to populate this field lives for some time.
    request.set_intent(user_data_auth::AUTH_INTENT_DECRYPT);
  }
  std::optional<AuthIntent> auth_intent = AuthIntentFromProto(request.intent());
  if (!auth_intent.has_value()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthNoIntentInStartAuthSession),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot}),
            user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_MOUNT_FATAL));
    return;
  }

  base::UnguessableToken token = auth_session_manager_->CreateAuthSession(
      GetAccountId(request.account_id()),
      {.is_ephemeral_user = is_ephemeral_user, .intent = *auth_intent});

  // Now that the session exists, queue up the work to run on it.
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInStartAuthSession),
      token, std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::StartAuthSessionWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::StartAuthSessionWithSession(
    user_data_auth::StartAuthSessionRequest request,
    OnDoneCallback<user_data_auth::StartAuthSessionReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::StartAuthSessionReply reply;
  reply.set_auth_session_id(auth_session->serialized_token());
  reply.set_broadcast_id(auth_session->serialized_public_token());
  reply.set_user_exists(auth_session->user_exists());

  const AuthFactorMap& auth_factor_map = auth_factor_manager_->GetAuthFactorMap(
      auth_session->obfuscated_username());
  if (auth_factor_map.empty() &&
      (auth_session->user_exists() && !auth_session->ephemeral_user())) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthNotConfiguredInStartAuthSession),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kDeleteVault,
                            PossibleAction::kAuth}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_UNUSABLE_VAULT));
    return;
  }

  // Discover any available auth factors from the AuthSession.
  std::set<std::string> listed_auth_factor_labels;
  for (AuthFactorMap::ValueView stored_auth_factor : auth_factor_map) {
    const AuthFactor& auth_factor = stored_auth_factor.auth_factor();
    AuthFactorDriver& factor_driver =
        auth_factor_driver_manager_->GetDriver(auth_factor.type());

    std::optional<user_data_auth::AuthFactor> proto_factor =
        factor_driver.ConvertToProto(auth_factor.label(),
                                     auth_factor.metadata());
    if (proto_factor.has_value()) {
      // Only output one factor per label.
      auto [unused, was_inserted] =
          listed_auth_factor_labels.insert(auth_factor.label());
      if (!was_inserted) {
        continue;
      }

      // Only populate reply with AuthFactors that support the intended form of
      // authentication.
      // AuthFactorWithStatus is populated irresptive of what is available or
      // not.
      auto user_policy_file_status =
          LoadUserPolicyFile(auth_session->obfuscated_username());
      if (!user_policy_file_status.ok()) {
        ReplyWithError(
            std::move(on_done), reply,
            MakeStatus<CryptohomeError>(
                CRYPTOHOME_ERR_LOC(
                    kLocCouldntLoadUserPolicyFileInStartAuthSession),
                ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                                PossibleAction::kReboot})));
        return;
      }
      auto user_policy = (*user_policy_file_status)->GetUserPolicy();
      if (!user_policy.has_value()) {
        ReplyWithError(
            std::move(on_done), reply,
            MakeStatus<CryptohomeError>(
                CRYPTOHOME_ERR_LOC(kLocCouldntGetUserPolicyInStartAuthSession),
                ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                                PossibleAction::kReboot})));
        return;
      }
      auto supported_intents = GetSupportedIntents(
          auth_session->obfuscated_username(), auth_factor.type(),
          *auth_factor_driver_manager_,
          GetAuthFactorPolicyFromUserPolicy(user_policy, auth_factor.type()),
          /*only_light_auth=*/false);
      std::optional<AuthIntent> requested_intent =
          AuthIntentFromProto(request.intent());
      user_data_auth::AuthFactorWithStatus auth_factor_with_status;
      auth_factor_with_status.mutable_auth_factor()->CopyFrom(
          proto_factor.value());

      for (const auto& auth_intent : supported_intents) {
        auth_factor_with_status.add_available_for_intents(
            AuthIntentToProto(auth_intent));
        if (requested_intent && auth_intent == requested_intent) {
          *reply.add_auth_factors() = std::move(*proto_factor);
        }
      }
      user_data_auth::StatusInfo& status_info =
          *auth_factor_with_status.mutable_status_info();
      auto delay = factor_driver.GetFactorDelay(
          auth_session->obfuscated_username(), auth_factor);
      if (delay.ok()) {
        status_info.set_time_available_in(
            delay->is_max() ? std::numeric_limits<uint64_t>::max()
                            : delay->InMilliseconds());
      }
      auto expiration_delay = factor_driver.GetTimeUntilExpiration(
          auth_session->obfuscated_username(), auth_factor);
      if (expiration_delay.ok()) {
        status_info.set_time_expiring_in(expiration_delay->InMilliseconds());
      } else {
        // Error getting the expiration time. Treat it as won't expire.
        status_info.set_time_expiring_in(std::numeric_limits<uint64_t>::max());
      }
      *reply.add_configured_auth_factors_with_status() =
          std::move(auth_factor_with_status);
    }
  }

  // The associated UserSession (if there is one) may also have some factors of
  // its own, via verifiers. However, these are only available if the request is
  // for a verify-only session.
  //
  // This is done after the persistent factors are looked up because if a
  // persistent factor also has a verifier then we only want output from the
  // persistent factor data.
  if (request.intent() == user_data_auth::AUTH_INTENT_VERIFY_ONLY) {
    if (UserSession* user_session =
            sessions_->Find(GetAccountId(request.account_id()))) {
      for (const CredentialVerifier* verifier :
           user_session->GetCredentialVerifiers()) {
        const AuthFactorDriver& factor_driver =
            auth_factor_driver_manager_->GetDriver(
                verifier->auth_factor_type());
        if (auto proto_factor = factor_driver.ConvertToProto(
                verifier->auth_factor_label(),
                verifier->auth_factor_metadata())) {
          auto [unused, was_inserted] =
              listed_auth_factor_labels.insert(verifier->auth_factor_label());
          if (was_inserted) {
            user_data_auth::AuthFactorWithStatus auth_factor_with_status;
            auth_factor_with_status.mutable_auth_factor()->CopyFrom(
                *proto_factor);
            auth_factor_with_status.add_available_for_intents(
                AuthIntentToProto(AuthIntent::kVerifyOnly));
            *reply.add_auth_factors() = std::move(*proto_factor);
            *reply.add_configured_auth_factors_with_status() =
                std::move(auth_factor_with_status);
          }
        }
      }
    }
  }

  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::InvalidateAuthSession(
    user_data_auth::InvalidateAuthSessionRequest request,
    OnDoneCallback<user_data_auth::InvalidateAuthSessionReply> on_done) {
  AssertOnMountThread();

  user_data_auth::InvalidateAuthSessionReply reply;
  if (auth_session_manager_->RemoveAuthSession(request.auth_session_id())) {
    LOG(INFO) << "AuthSession: invalidated.";
  }

  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::ExtendAuthSession(
    user_data_auth::ExtendAuthSessionRequest request,
    OnDoneCallback<user_data_auth::ExtendAuthSessionReply> on_done) {
  AssertOnMountThread();

  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInExtendAuthSession),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInExtendAuthSession),
      std::move(request), std::move(on_done),
      base::BindOnce(
          [](user_data_auth::ExtendAuthSessionRequest request,
             OnDoneCallback<user_data_auth::ExtendAuthSessionReply> on_done,
             InUseAuthSession auth_session) {
            user_data_auth::ExtendAuthSessionReply reply;

            // Extend specified AuthSession.
            auto timer_extension =
                request.extension_duration() != 0
                    ? base::Seconds(request.extension_duration())
                    : kDefaultExtensionTime;
            CryptohomeStatus result =
                auth_session.ExtendTimeout(timer_extension);
            if (!result.ok()) {
              result = MakeStatus<CryptohomeError>(
                           CRYPTOHOME_ERR_LOC(
                               kLocUserDataAuthExtendFailedInExtendAuthSession))
                           .Wrap(std::move(result));
            }
            LOG(INFO) << "AuthSession: Extended by " << timer_extension;
            reply.set_seconds_left(auth_session.GetRemainingTime().InSeconds());
            ReplyWithError(std::move(on_done), reply, std::move(result));
          }));
}

CryptohomeStatusOr<UserSession*> UserDataAuth::GetMountableUserSession(
    AuthSession* auth_session) {
  AssertOnMountThread();

  const ObfuscatedUsername& obfuscated_username =
      auth_session->obfuscated_username();

  // Check no guest is mounted.
  UserSession* const guest_session = sessions_->Find(guest_user_);
  if (guest_session && guest_session->IsActive()) {
    LOG(ERROR) << "Can not mount non-anonymous while guest session is active.";
    return MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthGuestAlreadyMountedInGetMountableUS),
        ErrorActionSet({PossibleAction::kReboot}),
        user_data_auth::CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY);
  }

  // Check the user is not already mounted.
  UserSession* const session = GetOrCreateUserSession(auth_session->username());
  if (session->IsActive()) {
    LOG(ERROR) << "User is already mounted: " << obfuscated_username;
    return MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(
            kLocUserDataAuthSessionAlreadyMountedInGetMountableUS),
        ErrorActionSet({PossibleAction::kReboot}),
        user_data_auth::CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY);
  }

  return session;
}

void UserDataAuth::PreMountHook(const ObfuscatedUsername& obfuscated_username) {
  AssertOnMountThread();

  LOG(INFO) << "Started mounting for: " << obfuscated_username;

  // Any non-guest mount attempt triggers InstallAttributes finalization.
  // The return value is ignored as it is possible we're pre-ownership.
  // The next login will assure finalization if possible.
  if (device_management_client_->IsInstallAttributesFirstInstall()) {
    std::ignore = device_management_client_->InstallAttributesFinalize();
  }
  // Removes all ephemeral cryptohomes owned by anyone other than the owner
  // user (if set) and non ephemeral users, regardless of free disk space.
  // Note that a fresh policy value is read here, which in theory can conflict
  // with the one used for calculation of |mount_args.is_ephemeral|. However,
  // this inconsistency (whose probability is anyway pretty low in practice)
  // should only lead to insignificant transient glitches, like an attempt to
  // mount a non existing anymore cryptohome.
  homedirs_->RemoveCryptohomesBasedOnPolicy();
}

void UserDataAuth::PostMountHook(UserSession* user_session,
                                 const MountStatus& status) {
  AssertOnMountThread();

  if (!status.ok()) {
    LOG(ERROR) << "Finished mounting with status code: " << status;
    return;
  }
  LOG(INFO) << "Mount succeeded.";
  InitializePkcs11(user_session);
}

CryptohomeStatus UserDataAuth::TerminateAuthSessionsAndClearLoadedState() {
  auth_session_manager_->RemoveAllAuthSessions();
  auth_factor_manager_->DiscardAllAuthFactorMaps();
  RETURN_IF_ERROR(uss_manager_->DiscardAllEncrypted());
  return OkStatus<CryptohomeError>();
}

libstorage::StorageContainerType
UserDataAuth::DbusEncryptionTypeToContainerType(
    user_data_auth::VaultEncryptionType type) {
  switch (type) {
    case user_data_auth::VaultEncryptionType::CRYPTOHOME_VAULT_ENCRYPTION_ANY:
      return libstorage::StorageContainerType::kUnknown;
    case user_data_auth::VaultEncryptionType::
        CRYPTOHOME_VAULT_ENCRYPTION_ECRYPTFS:
      return libstorage::StorageContainerType::kEcryptfs;
    case user_data_auth::VaultEncryptionType::
        CRYPTOHOME_VAULT_ENCRYPTION_FSCRYPT:
      return libstorage::StorageContainerType::kFscrypt;
    case user_data_auth::VaultEncryptionType::
        CRYPTOHOME_VAULT_ENCRYPTION_DMCRYPT:
      return libstorage::StorageContainerType::kDmcrypt;
    default:
      // Default cuz proto3 enum sentinels, that's why -_-
      return libstorage::StorageContainerType::kUnknown;
  }
}

void UserDataAuth::PrepareGuestVault(
    user_data_auth::PrepareGuestVaultRequest request,
    OnDoneCallback<user_data_auth::PrepareGuestVaultReply> on_done) {
  AssertOnMountThread();
  LOG(INFO) << "Preparing guest vault";

  // Send a mount starting signal.
  user_data_auth::MountStarted start_signal;
  start_signal.set_operation_id(base::RandUint64());
  signalling_intf_->SendMountStarted(start_signal);
  auto on_done_with_signal = base::BindOnce(
      &SignalMountCompletedThenDone<user_data_auth::PrepareGuestVaultReply>,
      signalling_intf_, std::move(start_signal), std::move(on_done));

  CryptohomeStatus status = PrepareGuestVaultImpl();

  // Send the mount completed signal and then the RPC reply.
  user_data_auth::PrepareGuestVaultReply reply;
  reply.set_sanitized_username(*SanitizeUserName(guest_user_));
  ReplyWithError(std::move(on_done_with_signal), reply, status);
  return;
}

void UserDataAuth::PrepareEphemeralVault(
    user_data_auth::PrepareEphemeralVaultRequest request,
    OnDoneCallback<user_data_auth::PrepareEphemeralVaultReply> on_done) {
  AssertOnMountThread();
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthNoAuthSessionInPrepareEphemeralVault),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::PrepareEphemeralVaultWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::PrepareEphemeralVaultWithSession(
    user_data_auth::PrepareEphemeralVaultRequest request,
    OnDoneCallback<user_data_auth::PrepareEphemeralVaultReply> on_done,
    InUseAuthSession auth_session) {
  AssertOnMountThread();
  LOG(INFO) << "Preparing ephemeral vault";

  // Send a mount starting signal and wrap the on_done callback to send the
  // completion signal.
  user_data_auth::MountStarted start_signal;
  start_signal.set_operation_id(base::RandUint64());
  signalling_intf_->SendMountStarted(start_signal);
  auto on_done_with_signal = base::BindOnce(
      &SignalMountCompletedThenDone<user_data_auth::PrepareEphemeralVaultReply>,
      signalling_intf_, std::move(start_signal), std::move(on_done));

  user_data_auth::PrepareEphemeralVaultReply reply;

  // If there are no active sessions, attempt to account for cryptohome restarts
  // after crashing.
  if (sessions_->size() != 0 || CleanUpStaleMounts(false)) {
    LOG(ERROR) << "Can not mount ephemeral while other sessions are active.";
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthOtherSessionActiveInPrepareEphemeralVault),
            ErrorActionSet({PossibleAction::kReboot}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY));
    return;
  }

  if (!auth_session->ephemeral_user()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthNonEphemeralAuthSessionInPrepareEphemeralVault),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot,
                            PossibleAction::kPowerwash}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }

  CryptohomeStatusOr<UserSession*> session_status =
      GetMountableUserSession(auth_session.Get());
  if (!session_status.ok()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthGetSessionFailedInPrepareEphemeralVault))
            .Wrap(std::move(session_status).err_status()));
    return;
  }

  PreMountHook(auth_session->obfuscated_username());
  ReportTimerStart(kMountExTimer);
  MountStatus mount_status =
      session_status.value()->MountEphemeral(auth_session->username());
  ReportTimerStop(kMountExTimer);
  PostMountHook(session_status.value(), mount_status);
  if (!mount_status.ok()) {
    RemoveInactiveUserSession(auth_session->username());
    ReplyWithError(std::move(on_done_with_signal), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(
                           kLocUserDataAuthMountFailedInPrepareEphemeralVault))
                       .Wrap(std::move(mount_status).err_status()));
    return;
  }

  // Let the auth session perform any finalization operations for a newly
  // created user.
  CryptohomeStatus ret = auth_session->OnUserCreated();
  if (!ret.ok()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthFinalizeFailedInPrepareEphemeralVault))
            .Wrap(std::move(ret)));
    return;
  }

  PopulateAuthSessionProperties(auth_session, reply.mutable_auth_properties());
  reply.set_sanitized_username(*auth_session->obfuscated_username());
  ReplyWithError(std::move(on_done_with_signal), reply,
                 OkStatus<CryptohomeError>());
}

void UserDataAuth::PreparePersistentVault(
    user_data_auth::PreparePersistentVaultRequest request,
    OnDoneCallback<user_data_auth::PreparePersistentVaultReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotFoundInPreparePersistentVault),
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotAuthInPreparePersistentVault),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::PreparePersistentVaultWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::PreparePersistentVaultWithSession(
    user_data_auth::PreparePersistentVaultRequest request,
    OnDoneCallback<user_data_auth::PreparePersistentVaultReply> on_done,
    InUseAuthSession auth_session) {
  LOG(INFO) << "Preparing persistent vault";

  // Send a mount starting signal.
  user_data_auth::MountStarted start_signal;
  start_signal.set_operation_id(base::RandUint64());
  signalling_intf_->SendMountStarted(start_signal);
  auto on_done_with_signal = base::BindOnce(
      &SignalMountCompletedThenDone<
          user_data_auth::PreparePersistentVaultReply>,
      signalling_intf_, std::move(start_signal), std::move(on_done));

  CryptohomeVault::Options options = {
      .force_type =
          DbusEncryptionTypeToContainerType(request.encryption_type()),
      .block_ecryptfs = request.block_ecryptfs(),
  };
  CryptohomeStatus status = PreparePersistentVaultImpl(auth_session, options);

  if (status.ok() && !auth_session->obfuscated_username()->empty()) {
    // Send UMA with VK stats once per successful mount operation.
    keyset_management_->RecordAllVaultKeysetMetrics(
        auth_session->obfuscated_username());
  }

  // Send the mount completed signal and then the RPC reply.
  user_data_auth::PreparePersistentVaultReply reply;
  reply.set_sanitized_username(*auth_session->obfuscated_username());
  ReplyWithError(std::move(on_done_with_signal), reply, status);
}

void UserDataAuth::PrepareVaultForMigration(
    user_data_auth::PrepareVaultForMigrationRequest request,
    OnDoneCallback<user_data_auth::PrepareVaultForMigrationReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotFoundInPrepareVaultForMigration),
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotAuthInPrepareVaultForMigration),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::PrepareVaultForMigrationWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::PrepareVaultForMigrationWithSession(
    user_data_auth::PrepareVaultForMigrationRequest request,
    OnDoneCallback<user_data_auth::PrepareVaultForMigrationReply> on_done,
    InUseAuthSession auth_session) {
  AssertOnMountThread();
  LOG(INFO) << "Preparing vault for migration";

  // Send a mount starting signal.
  user_data_auth::MountStarted start_signal;
  start_signal.set_operation_id(base::RandUint64());
  signalling_intf_->SendMountStarted(start_signal);
  auto on_done_with_signal = base::BindOnce(
      &SignalMountCompletedThenDone<
          user_data_auth::PrepareVaultForMigrationReply>,
      signalling_intf_, std::move(start_signal), std::move(on_done));

  CryptohomeVault::Options options = {
      .migrate = true,
  };
  CryptohomeStatus status = PreparePersistentVaultImpl(auth_session, options);

  // Send the mount completed signal and then the RPC reply.
  user_data_auth::PrepareVaultForMigrationReply reply;
  reply.set_sanitized_username(*auth_session->obfuscated_username());
  ReplyWithError(std::move(on_done_with_signal), reply, status);
}

void UserDataAuth::CreatePersistentUser(
    user_data_auth::CreatePersistentUserRequest request,
    OnDoneCallback<user_data_auth::CreatePersistentUserReply> on_done) {
  AssertOnMountThread();
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInCreatePersistentUser),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::CreatePersistentUserWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::CreatePersistentUserWithSession(
    user_data_auth::CreatePersistentUserRequest request,
    OnDoneCallback<user_data_auth::CreatePersistentUserReply> on_done,
    InUseAuthSession auth_session) {
  LOG(INFO) << "Creating persistent user";
  // Record the time in between now and when this function exits.
  absl::Cleanup report_time = [start_time = base::TimeTicks::Now()]() {
    ReportTimerDuration(kCreatePersistentUserTimer, start_time, "");
  };

  // Send the auth started signal and wrap the completion callback in a sender
  // for the completion signal.
  uint64_t operation_id = base::RandUint64();
  user_data_auth::AuthenticateStarted start_signal;
  start_signal.set_operation_id(operation_id);
  start_signal.set_user_creation(true);
  start_signal.set_username(*auth_session->username());
  start_signal.set_sanitized_username(*auth_session->obfuscated_username());
  signalling_intf_->SendAuthenticateStarted(start_signal);
  auto on_done_with_signal = base::BindOnce(
      &SignalAuthCompletedThenDone<user_data_auth::CreatePersistentUserReply>,
      signalling_intf_, std::move(start_signal), std::move(on_done));

  user_data_auth::CreatePersistentUserReply reply;
  if (auth_session->ephemeral_user()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthCreatePersistentUserInEphemeralSession),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot,
                            PossibleAction::kPowerwash}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }

  const ObfuscatedUsername& obfuscated_username =
      auth_session->obfuscated_username();

  // This checks presence of the actual encrypted vault. We fail if Create is
  // called while actual persistent vault is present.
  auto exists_or = homedirs_->CryptohomeExists(obfuscated_username);
  if (exists_or.ok() && exists_or.value()) {
    LOG(ERROR) << "User already exists: " << obfuscated_username;
    // TODO(b/208898186, dlunev): replace with a more appropriate error
    ReplyWithError(std::move(on_done_with_signal), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(
                           kLocUserDataAuthUserExistsInCreatePersistentUser),
                       ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                                       PossibleAction::kDeleteVault}),
                       user_data_auth::CryptohomeErrorCode::
                           CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY));
    return;
  }

  if (!exists_or.ok()) {
    MountError mount_error = exists_or.err_status()->error();
    LOG(ERROR) << "Failed to query vault existance for: " << obfuscated_username
               << ", code: " << mount_error;
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeMountError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthCheckExistsFailedInCreatePersistentUser),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot}),
            mount_error, MountErrorToCryptohomeError(mount_error)));
    return;
  }

  // This check seems superfluous after the `HomeDirs::CryptohomeExists()` check
  // above, but it can happen that the user directory exists without any vault
  // in it. We perform both checks for completeness and also to distinguish
  // between these two error cases in metrics and logs.
  if (auth_session->user_exists()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthUserDirExistsInCreatePersistentUser),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kDeleteVault,
                            PossibleAction::kPowerwash}),
            user_data_auth::CRYPTOHOME_ERROR_MOUNT_MOUNT_POINT_BUSY));
    return;
  }

  // This checks and creates if missing the user's directory in shadow root.
  // We need to disambiguate with vault presence, because it is possible that
  // we have an empty shadow root directory for the user left behind after
  // removing a profile (due to a bug or for some other reasons). To avoid weird
  // failures in the case, just let the creation succeed, since the user is
  // effectively not there. Eventually |Exists| will check for the presence of
  // the USS/auth factors to determine if the user is intended to be there.
  // This call will not create the actual volume (for efficiency, idempotency,
  // and because that would require going the full sequence of mount and unmount
  // because of ecryptfs possibility).
  if (!homedirs_->Exists(obfuscated_username) &&
      !homedirs_->Create(obfuscated_username)) {
    LOG(ERROR) << "Failed to create shadow directory for: "
               << obfuscated_username;
    ReplyWithError(std::move(on_done_with_signal), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(
                           kLocUserDataAuthCreateFailedInCreatePersistentUser),
                       ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                                       PossibleAction::kReboot,
                                       PossibleAction::kPowerwash}),
                       user_data_auth::CryptohomeErrorCode::
                           CRYPTOHOME_ERROR_BACKING_STORE_FAILURE));
    return;
  }

  // Let the auth session perform any finalization operations for a newly
  // created user.
  CryptohomeStatus ret = auth_session->OnUserCreated();
  if (!ret.ok()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthFinalizeFailedInCreatePersistentUser))
            .Wrap(std::move(ret)));
    return;
  }

  PopulateAuthSessionProperties(auth_session, reply.mutable_auth_properties());
  reply.set_sanitized_username(*auth_session->obfuscated_username());
  ReplyWithError(std::move(on_done_with_signal), reply,
                 OkStatus<CryptohomeError>());
}

CryptohomeStatus UserDataAuth::PrepareGuestVaultImpl() {
  AssertOnMountThread();

  // If there are no active sessions, attempt to account for cryptohome restarts
  // after crashing.
  if (sessions_->size() != 0 || CleanUpStaleMounts(false)) {
    LOG(ERROR) << "Can not mount guest while other sessions are active.";
    return MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(
            kLocUserDataAuthOtherSessionActiveInPrepareGuestVault),
        ErrorActionSet({PossibleAction::kReboot}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_MOUNT_FATAL);
  }

  UserSession* const session = GetOrCreateUserSession(guest_user_);

  LOG(INFO) << "Started mounting for guest";
  ReportTimerStart(kMountGuestExTimer);
  MountStatus status = session->MountGuest();
  ReportTimerStop(kMountGuestExTimer);
  if (!status.ok()) {
    CHECK(status->mount_error() != MOUNT_ERROR_NONE);
    LOG(ERROR) << "Finished mounting with status code: "
               << status->mount_error();
    RemoveInactiveUserSession(guest_user_);
    return MakeStatus<CryptohomeError>(
               CRYPTOHOME_ERR_LOC(
                   kLocUserDataAuthMountFailedInPrepareGuestVault))
        .Wrap(std::move(status));
  }
  LOG(INFO) << "Mount succeeded.";
  return OkStatus<CryptohomeError>();
}

CryptohomeStatus UserDataAuth::PreparePersistentVaultImpl(
    InUseAuthSession& auth_session,
    const CryptohomeVault::Options& vault_options) {
  AssertOnMountThread();

  // If there are no active sessions, attempt to account for cryptohome restarts
  // after crashing.
  if (sessions_->empty()) {
    CleanUpStaleMounts(false);
  }

  if (auth_session->ephemeral_user()) {
    return MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(
            kLocUserDataAuthEphemeralAuthSessionAttemptPreparePersistentVault),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                        PossibleAction::kDeleteVault, PossibleAction::kReboot,
                        PossibleAction::kPowerwash}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
  }

  const ObfuscatedUsername& obfuscated_username =
      auth_session->obfuscated_username();
  if (!homedirs_->Exists(obfuscated_username)) {
    return MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthNonExistentInPreparePersistentVault),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                        PossibleAction::kDeleteVault, PossibleAction::kReboot,
                        PossibleAction::kPowerwash}),
        user_data_auth::CryptohomeErrorCode::
            CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND);
  }

  CryptohomeStatusOr<UserSession*> session_status =
      GetMountableUserSession(auth_session.Get());
  if (!session_status.ok()) {
    return MakeStatus<CryptohomeError>(
               CRYPTOHOME_ERR_LOC(
                   kLocUserDataAuthGetSessionFailedInPreparePersistentVault))
        .Wrap(std::move(session_status).err_status());
  }

  // User session and kiosk session cannot co-exist.
  bool are_active_sessions = false;
  for (const auto& [username, session] : *sessions_) {
    if (session.IsActive()) {
      are_active_sessions = true;
      // Don't mount user cryptohome if there is a mounted kiosk session.
      if (IsKioskUser(SanitizeUserName(username))) {
        return MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthUnexpectedKioskMountInPreparePersistent),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT);
      }
    }
  }
  // Don't mount if the current request is for a kiosk session, there
  // are other active mounts.
  if (are_active_sessions && IsKioskUser(auth_session->obfuscated_username())) {
    return MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthExitingMountsInPreparePersistent),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                        PossibleAction::kReboot}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
  }

  PreMountHook(obfuscated_username);
  if (low_disk_space_handler_) {
    low_disk_space_handler_->disk_cleanup()->FreeDiskSpaceDuringLogin(
        obfuscated_username);
  }
  ReportTimerStart(kMountExTimer);
  MountStatus mount_status = session_status.value()->MountVault(
      auth_session->username(), auth_session->file_system_keyset(),
      vault_options);
  ReportTimerStop(kMountExTimer);
  PostMountHook(session_status.value(), mount_status);
  if (!mount_status.ok()) {
    RemoveInactiveUserSession(auth_session->username());
    return MakeStatus<CryptohomeError>(
               CRYPTOHOME_ERR_LOC(
                   kLocUserDataAuthMountFailedInPreparePersistentVault))
        .Wrap(std::move(mount_status).err_status());
  }
  return OkStatus<CryptohomeError>();
}

bool UserDataAuth::IsKioskUser(ObfuscatedUsername obfuscated) {
  // Load the AuthFactorMap for the obfuscated username.
  AuthFactorMap& auth_factor_map =
      auth_factor_manager_->GetAuthFactorMap(obfuscated);
  // Populate the response from the items in the AuthFactorMap.
  for (AuthFactorMap::ValueView item : auth_factor_map) {
    if (item.auth_factor().type() == AuthFactorType::kKiosk) {
      return true;
    }
  }
  return false;
}

void UserDataAuth::EvictDeviceKey(
    user_data_auth::EvictDeviceKeyRequest request,
    OnDoneCallback<user_data_auth::EvictDeviceKeyReply> on_done) {
  // This method touches the |sessions_| object so it needs to run on
  // |mount_thread_|
  AssertOnMountThread();
  user_data_auth::EvictDeviceKeyReply reply;
  // This loops through all active and mounted user sessions and evicts the
  // device key for each one. In practice having multiple mounts is not an
  // expected use case, but as a user_id is not specified, it should iterate
  // through all the active sessions. We consider "cryptohome" to be mounted if
  // any existing session is mounted.
  std::optional<CryptohomeStatus> eviction_result = std::nullopt;
  for (const auto& [unused, session] : *sessions_) {
    // Check if the session is actively mounted.
    const ObfuscatedUsername obfuscated_username =
        SanitizeUserName(session.GetUsername());
    if (!session.IsActive()) {
      LOG(ERROR) << "Session is not mounted: " << obfuscated_username;
      continue;
    }

    if (!homedirs_->Exists(obfuscated_username)) {
      LOG(ERROR) << "Home directory of " << obfuscated_username
                 << "does not exist.";
      continue;
    }

    // An active and mounted session was found.
    MountStatus mount_status = session.EvictDeviceKey();
    if (!mount_status.ok()) {
      LOG(ERROR) << "Couldn't evict key of " << obfuscated_username;
      // Only record an error for the first element/session in |sessions_|.
      if (!eviction_result)
        eviction_result = std::move(mount_status);
      continue;
    }
    // If any session succeeded the operation as a whole is considered
    // successful
    eviction_result = OkStatus<CryptohomeError>();
  }

  // Did not find any mounted session, eviction_result was never initialized.
  if (!eviction_result) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthNoActiveMountInEvictDeviceKey),
            ErrorActionSet({PossibleAction::kAuth, PossibleAction::kReboot}),
            user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_MOUNT_FATAL));
    return;
  }

  // Return results of EvictDeviceKey(), either OK or error of the first mounted
  // session.
  // Unwrap status into result to satisfy StatusChain move semantics.
  auto result = std::move(eviction_result.value());
  if (!result.ok()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthKeyEvictionFailedInEvictDeviceKey),
            ErrorActionSet({PossibleAction::kReboot}),
            user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_MOUNT_FATAL)
            .Wrap(std::move(result)));
    return;
  }

  // Persist the Suspend ID of the current suspend attempt.
  if (!base::WriteFile(base::FilePath(kEncDeviceEvictedPath),
                       std::to_string(request.eviction_id()))) {
    LOG(ERROR) << "Couldn't create " << kEncDeviceEvictedPath;
  }

  // If key eviction is successful, we should invalidate all authenticated
  // AuthSessions, similar to unmounting.
  if (CryptohomeStatus status = TerminateAuthSessionsAndClearLoadedState();
      !status.ok()) {
    ReplyWithError(std::move(on_done), reply, std::move(status));
    return;
  }
  LOG(INFO) << "Filesystem key is successfully evicted from RAM disk device.";
  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::AddAuthFactor(
    user_data_auth::AddAuthFactorRequest request,
    OnDoneCallback<user_data_auth::AddAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthAuthSessionNotFoundInAddAuthFactor),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthAuthSessionNotAuthInAddAuthFactor),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::AddAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::AddAuthFactorWithSession(
    user_data_auth::AddAuthFactorRequest request,
    OnDoneCallback<user_data_auth::AddAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  // Wrap callback to signal AuthFactorAdded.
  OnDoneCallback<user_data_auth::AddAuthFactorReply>
      on_done_wrapped_with_signal_ = base::BindOnce(
          [](SignallingInterface* signalling_intf, std::string broadcast_id,
             OnDoneCallback<user_data_auth::AddAuthFactorReply> cb,
             const user_data_auth::AddAuthFactorReply& reply) {
            user_data_auth::AuthFactorAdded completed_proto;
            if (!reply.has_error_info()) {
              completed_proto.mutable_auth_factor()->CopyFrom(
                  reply.added_auth_factor().auth_factor());
              completed_proto.set_broadcast_id(broadcast_id);
              signalling_intf->SendAuthFactorAdded(completed_proto);
            }
            std::move(cb).Run(reply);
          },
          signalling_intf_, auth_session->serialized_public_token(),
          std::move(on_done));

  user_data_auth::AddAuthFactorReply reply;

  // Populate the request auth factor with accurate sysinfo.
  PopulateAuthFactorProtoWithSysinfo(*request.mutable_auth_factor());
  auto user_policy_file_status =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file_status.ok()) {
    ReplyWithError(
        std::move(on_done_wrapped_with_signal_), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocCouldntLoadUserPolicyFileInAddAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot})));
    return;
  }
  auto* session_decrypt = auth_session->GetAuthForDecrypt();
  if (!session_decrypt) {
    ReplyWithError(
        std::move(on_done_wrapped_with_signal_), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUnauthedInAddAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
    return;
  }
  const Username& username = auth_session->username();
  session_decrypt->AddAuthFactor(
      request,
      base::BindOnce(
          &ReplyWithAuthFactorStatus<user_data_auth::AddAuthFactorReply>,
          std::move(auth_session).BindForCallback(),
          user_policy_file_status.value(), auth_factor_manager_,
          auth_factor_driver_manager_, sessions_->Find(username),
          request.auth_factor().label(),
          std::move(on_done_wrapped_with_signal_)));
}

void UserDataAuth::AuthenticateAuthFactor(
    user_data_auth::AuthenticateAuthFactorRequest request,
    OnDoneCallback<user_data_auth::AuthenticateAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInAuthAuthFactor),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::AuthenticateAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::AuthenticateAuthFactorWithSession(
    user_data_auth::AuthenticateAuthFactorRequest request,
    OnDoneCallback<user_data_auth::AuthenticateAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  // We will tie the life time of the authenticate event with the wrapped
  // on_done callback.
  hwsec::ScopedEvent event;
  if (hwsec_) {
    event = hwsec_->NotifyAuthenticateEvent().value_or(hwsec::ScopedEvent());
  }

  // Extract the auth factor type.
  std::optional<AuthFactorType> auth_factor_type =
      DetermineFactorTypeFromAuthInput(request.auth_input());
  user_data_auth::AuthFactorType auth_factor_type_proto = AuthFactorTypeToProto(
      auth_factor_type.value_or(AuthFactorType::kUnspecified));

  // Send the auth started signal and wrap the completion callback in a sender
  // for the completion signal.
  uint64_t operation_id = base::RandUint64();
  user_data_auth::AuthenticateStarted start_signal;
  start_signal.set_operation_id(operation_id);
  start_signal.set_auth_factor_type(auth_factor_type_proto);
  start_signal.set_username(*auth_session->username());
  start_signal.set_sanitized_username(*auth_session->obfuscated_username());
  signalling_intf_->SendAuthenticateStarted(start_signal);
  auto on_done_with_signal = base::BindOnce(
      &SignalAuthCompletedThenDone<user_data_auth::AuthenticateAuthFactorReply>,
      signalling_intf_, std::move(start_signal), std::move(on_done));

  user_data_auth::AuthenticateAuthFactorReply reply;

  // |auth_factor_labels| is intended to replace |auth_factor_label|, reject
  // requests specifying both fields.
  // TODO(b/265151254): Deprecate |auth_factor_label| and remove this check.
  if (!request.auth_factor_label().empty() &&
      request.auth_factor_labels_size() > 0) {
    LOG(ERROR) << "Cannot accept request with both auth_factor_label and "
                  "auth_factor_labels.";
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataMalformedRequestInAuthAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }
  std::vector<std::string> auth_factor_labels;
  if (!request.auth_factor_label().empty()) {
    auth_factor_labels.push_back(request.auth_factor_label());
  } else {
    for (auto label : request.auth_factor_labels()) {
      auth_factor_labels.push_back(label);
    }
  }

  auto user_policy_file_status =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file_status.ok()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocCouldntLoadUserPolicyFileInAuthenticateAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot})));
    return;
  }

  SerializedUserAuthFactorTypePolicy auth_factor_type_policy;
  if (!auth_factor_type.has_value()) {
    ReplyWithError(
        std::move(on_done_with_signal), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthAuthFactorNotFoundInAuthenticateAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  } else {
    auth_factor_type_policy = GetAuthFactorPolicyFromUserPolicy(
        (*user_policy_file_status)->GetUserPolicy(), *auth_factor_type);
  }

  AuthSession::AuthenticateAuthFactorRequest authenticate_auth_factor_request{
      .auth_factor_labels = std::move(auth_factor_labels),
      .auth_input_proto = std::move(request.auth_input()),
      .flags =
          AuthSession::AuthenticateAuthFactorFlags{
              .force_full_auth = AuthSession::ForceFullAuthFlag::kNone},
  };

  AuthSession* auth_session_ptr = auth_session.Get();
  auth_session_ptr->AuthenticateAuthFactor(
      authenticate_auth_factor_request, auth_factor_type_policy,
      base::BindOnce(&HandleAuthenticationResult,
                     std::move(auth_session).BindForCallback(),
                     auth_factor_type_policy, std::move(on_done_with_signal)));
}

void UserDataAuth::UpdateAuthFactor(
    user_data_auth::UpdateAuthFactorRequest request,
    OnDoneCallback<user_data_auth::UpdateAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInUpdateAuthFactor),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInUpdateAuthFactor),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::UpdateAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::UpdateAuthFactorWithSession(
    user_data_auth::UpdateAuthFactorRequest request,
    OnDoneCallback<user_data_auth::UpdateAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  // Wrap callback to signal AuthFactorUpdated.
  OnDoneCallback<user_data_auth::UpdateAuthFactorReply>
      on_done_wrapped_with_signal_ = base::BindOnce(
          [](SignallingInterface* signalling_intf, std::string broadcast_id,
             OnDoneCallback<user_data_auth::UpdateAuthFactorReply> cb,
             const user_data_auth::UpdateAuthFactorReply& reply) {
            user_data_auth::AuthFactorUpdated completed_proto;

            if (reply.has_error_info() && reply.error_info().primary_action() ==
                                              user_data_auth::PRIMARY_NONE) {
              completed_proto.mutable_auth_factor()->CopyFrom(
                  reply.updated_auth_factor().auth_factor());
              completed_proto.set_broadcast_id(broadcast_id);
              signalling_intf->SendAuthFactorUpdated(completed_proto);
            }
            std::move(cb).Run(reply);
          },
          signalling_intf_, auth_session->serialized_public_token(),
          std::move(on_done));
  user_data_auth::UpdateAuthFactorReply reply;

  // Populate the request auth factor with accurate sysinfo.
  PopulateAuthFactorProtoWithSysinfo(*request.mutable_auth_factor());

  auto user_policy_file_status =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file_status.ok()) {
    ReplyWithError(
        std::move(on_done_wrapped_with_signal_), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocCouldntLoadUserPolicyFileInUpdateAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot})));
    return;
  }
  auto* session_decrypt = auth_session->GetAuthForDecrypt();
  if (!session_decrypt) {
    ReplyWithError(
        std::move(on_done_wrapped_with_signal_), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUnauthedInUpdateAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
    return;
  }
  const Username& username = auth_session->username();
  session_decrypt->UpdateAuthFactor(
      request,
      base::BindOnce(
          &ReplyWithAuthFactorStatus<user_data_auth::UpdateAuthFactorReply>,
          std::move(auth_session).BindForCallback(),
          user_policy_file_status.value(), auth_factor_manager_,
          auth_factor_driver_manager_, sessions_->Find(username),
          request.auth_factor().label(),
          std::move(on_done_wrapped_with_signal_)));
}

void UserDataAuth::UpdateAuthFactorMetadata(
    user_data_auth::UpdateAuthFactorMetadataRequest request,
    OnDoneCallback<user_data_auth::UpdateAuthFactorMetadataReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotFoundInUpdateAuthFactorMetadata),
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotAuthInUpdateAuthFactorMetadata),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::UpdateAuthFactorMetadataWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::UpdateAuthFactorMetadataWithSession(
    user_data_auth::UpdateAuthFactorMetadataRequest request,
    OnDoneCallback<user_data_auth::UpdateAuthFactorMetadataReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::UpdateAuthFactorMetadataReply reply;

  // Populate the request auth factor with accurate sysinfo.
  auto user_policy_file_status =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file_status.ok()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocCouldntLoadUserPolicyFileInUpdateAuthFactorMetadata),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot})));
    return;
  }
  AuthSession* auth_session_ptr = auth_session.Get();
  auto* session_decrypt = auth_session_ptr->GetAuthForDecrypt();
  if (!session_decrypt) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthUnauthedInUpdateAuthFactorMetadata),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
    return;
  }
  session_decrypt->UpdateAuthFactorMetadata(
      request,
      base::BindOnce(&ReplyWithAuthFactorStatus<
                         user_data_auth::UpdateAuthFactorMetadataReply>,
                     std::move(auth_session).BindForCallback(),
                     user_policy_file_status.value(), auth_factor_manager_,
                     auth_factor_driver_manager_,
                     sessions_->Find(auth_session_ptr->username()),
                     request.auth_factor().label(), std::move(on_done)));
}

void UserDataAuth::RelabelAuthFactor(
    user_data_auth::RelabelAuthFactorRequest request,
    OnDoneCallback<user_data_auth::RelabelAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInRelabelAuthFactor),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInRelabelAuthFactor),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::RelabelAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::RelabelAuthFactorWithSession(
    user_data_auth::RelabelAuthFactorRequest request,
    OnDoneCallback<user_data_auth::RelabelAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::RelabelAuthFactorReply reply;
  auto* session_decrypt = auth_session->GetAuthForDecrypt();
  if (!session_decrypt) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUnauthedInRelabelAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
    return;
  }

  // Load the user policy, also needed for the final result.
  auto user_policy_file =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file.ok()) {
    ReplyWithError(std::move(on_done), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(
                           kLocCouldntLoadUserPolicyFileInRelabelAuthFactor))
                       .Wrap(std::move(user_policy_file).err_status()));
    return;
  }

  // Execute the actual relabel.
  AuthSession* auth_session_ptr = auth_session.Get();
  session_decrypt->RelabelAuthFactor(
      request,
      base::BindOnce(
          &ReplyWithAuthFactorStatus<user_data_auth::RelabelAuthFactorReply>,
          std::move(auth_session).BindForCallback(), *user_policy_file,
          auth_factor_manager_, auth_factor_driver_manager_,
          sessions_->Find(auth_session_ptr->username()),
          request.new_auth_factor_label(), std::move(on_done)));
}

void UserDataAuth::ReplaceAuthFactor(
    user_data_auth::ReplaceAuthFactorRequest request,
    OnDoneCallback<user_data_auth::ReplaceAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInReplaceAuthFactor),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInReplaceAuthFactor),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::ReplaceAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::ReplaceAuthFactorWithSession(
    user_data_auth::ReplaceAuthFactorRequest request,
    OnDoneCallback<user_data_auth::ReplaceAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::ReplaceAuthFactorReply reply;
  auto* session_decrypt = auth_session->GetAuthForDecrypt();
  if (!session_decrypt) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUnauthedInReplaceAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
    return;
  }

  // Load the user policy, also needed for the final result.
  auto user_policy_file =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file.ok()) {
    ReplyWithError(std::move(on_done), reply,
                   MakeStatus<CryptohomeError>(
                       CRYPTOHOME_ERR_LOC(
                           kLocCouldntLoadUserPolicyFileInReplaceAuthFactor))
                       .Wrap(std::move(user_policy_file).err_status()));
    return;
  }

  // Execute the actual relabel.
  AuthSession* auth_session_ptr = auth_session.Get();
  session_decrypt->ReplaceAuthFactor(
      request,
      base::BindOnce(
          &ReplyWithAuthFactorStatus<user_data_auth::ReplaceAuthFactorReply>,
          std::move(auth_session).BindForCallback(), *user_policy_file,
          auth_factor_manager_, auth_factor_driver_manager_,
          sessions_->Find(auth_session_ptr->username()),
          request.auth_factor().label(), std::move(on_done)));
}

void UserDataAuth::RemoveAuthFactor(
    user_data_auth::RemoveAuthFactorRequest request,
    OnDoneCallback<user_data_auth::RemoveAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInRemoveAuthFactor),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInRemoveAuthFactor),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::RemoveAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::RemoveAuthFactorWithSession(
    user_data_auth::RemoveAuthFactorRequest request,
    OnDoneCallback<user_data_auth::RemoveAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::RemoveAuthFactorReply reply;
  auto* session_decrypt = auth_session->GetAuthForDecrypt();
  if (!session_decrypt) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthUnauthedInRemoveAuthFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_UNAUTHENTICATED_AUTH_SESSION));
    return;
  }

  user_data_auth::AuthFactorRemoved auth_factor_removed_msg;
  if (auto view = auth_factor_manager_
                      ->GetAuthFactorMap(auth_session->obfuscated_username())
                      .Find(request.auth_factor_label());
      view.has_value()) {
    const auto& af = view->auth_factor();
    const AuthFactorDriver& factor_driver =
        auth_factor_driver_manager_->GetDriver(af.type());

    auto af_proto = factor_driver.ConvertToProto(af.label(), af.metadata());
    if (af_proto.has_value()) {
      auth_factor_removed_msg.mutable_auth_factor()->CopyFrom(af_proto.value());
    }

    auth_factor_removed_msg.set_broadcast_id(
        auth_session->serialized_public_token());
  }

  // Wrap callback to signal AuthenticateAuthFactorCompleted.
  OnDoneCallback<user_data_auth::RemoveAuthFactorReply>
      on_done_wrapped_with_signal_cb = base::BindOnce(
          [](SignallingInterface* signalling_intf,
             user_data_auth::AuthFactorRemoved auth_factor_removed_msg,
             OnDoneCallback<user_data_auth::RemoveAuthFactorReply> cb,
             const user_data_auth::RemoveAuthFactorReply& reply) {
            if (!reply.has_error_info()) {
              signalling_intf->SendAuthFactorRemoved(auth_factor_removed_msg);
            }
            std::move(cb).Run(reply);
          },
          signalling_intf_, std::move(auth_factor_removed_msg),
          std::move(on_done));
  StatusCallback on_remove_auth_factor_finished =
      base::BindOnce(&ReplyWithStatus<user_data_auth::RemoveAuthFactorReply>,
                     std::move(auth_session).BindForCallback(),
                     std::move(on_done_wrapped_with_signal_cb));
  session_decrypt->RemoveAuthFactor(request,
                                    std::move(on_remove_auth_factor_finished));
}

void UserDataAuth::ListAuthFactors(
    user_data_auth::ListAuthFactorsRequest request,
    OnDoneCallback<user_data_auth::ListAuthFactorsReply> on_done) {
  AssertOnMountThread();
  user_data_auth::ListAuthFactorsReply reply;

  // Check whether user exists.
  // Compute the raw and sanitized user name from the request.
  Username username = GetAccountId(request.account_id());
  ObfuscatedUsername obfuscated_username = SanitizeUserName(username);
  UserSession* user_session = sessions_->Find(username);  // May be null!
  // If the user does not exist, we cannot return auth factors for it.
  bool is_persistent_user =
      (user_session && !user_session->IsEphemeral()) ||
      platform_->DirectoryExists(UserPath(obfuscated_username));
  bool is_ephemeral_user = user_session && user_session->IsEphemeral();
  if (!is_persistent_user && !is_ephemeral_user) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocUserDataAuthUserNonexistentInListAuthFactors),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }
  auto user_policy_file_status = LoadUserPolicyFile(obfuscated_username);
  if (!user_policy_file_status.ok()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocCouldntLoadUserPolicyFileInListAuthFactors),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                            PossibleAction::kReboot})));
    return;
  }

  // Helper function to filter out types of auth factor that are supported
  // internally but which should not be reported as supported in the public API.
  auto IsPublicType = [](AuthFactorType type) {
    switch (type) {
      case AuthFactorType::kPassword:
      case AuthFactorType::kPin:
      case AuthFactorType::kCryptohomeRecovery:
      case AuthFactorType::kKiosk:
      case AuthFactorType::kSmartCard:
      case AuthFactorType::kFingerprint:
        return true;
      case AuthFactorType::kLegacyFingerprint:
      case AuthFactorType::kUnspecified:
      default:
        return false;
    }
  };

  std::vector<AuthFactorType> supported_auth_factors;
  if (is_persistent_user) {
    // Prepare the response for configured AuthFactors (with status) with all of
    // the auth factors from the disk.

    // Load the AuthFactorMap.
    AuthFactorMap& auth_factor_map =
        auth_factor_manager_->GetAuthFactorMap(obfuscated_username);

    // Populate the response from the items in the AuthFactorMap.
    for (AuthFactorMap::ValueView item : auth_factor_map) {
      if (IsPublicType(item.auth_factor().type())) {
        auto auth_factor_with_status = GetAuthFactorWithStatus(
            obfuscated_username, *user_policy_file_status,
            auth_factor_driver_manager_, item.auth_factor());
        if (auth_factor_with_status.has_value()) {
          *reply.add_configured_auth_factors_with_status() =
              std::move(*auth_factor_with_status);
        }
      }
    }

    // Prepare the response for supported AuthFactors for the given user.
    // Since user is a persistent user this is determined based on the
    // underlying storage backend and the existing configured factors.

    // Turn the list of configured types into a set that we can use for
    // computing the list of supported factors.
    std::set<AuthFactorType> configured_types;
    for (const auto& configured_factor_status :
         reply.configured_auth_factors_with_status()) {
      if (auto type = AuthFactorTypeFromProto(
              configured_factor_status.auth_factor().type())) {
        configured_types.insert(*type);
      }
    }

    // Determine what auth factors are supported by going through the entire set
    // of auth factor types and checking each one.
    std::set<AuthFactorStorageType> configured_storages;
    configured_storages.insert(AuthFactorStorageType::kUserSecretStash);

    if (auth_factor_map.HasFactorWithStorage(
            AuthFactorStorageType::kVaultKeyset)) {
      configured_storages.insert(AuthFactorStorageType::kVaultKeyset);
    }

    for (auto proto_type :
         PROTOBUF_ENUM_ALL_VALUES(user_data_auth::AuthFactorType)) {
      std::optional<AuthFactorType> type = AuthFactorTypeFromProto(proto_type);
      if (!type || !IsPublicType(*type)) {
        continue;
      }
      const AuthFactorDriver& factor_driver =
          auth_factor_driver_manager_->GetDriver(*type);
      if (factor_driver.IsSupportedByStorage(configured_storages,
                                             configured_types) &&
          factor_driver.IsSupportedByHardware()) {
        reply.add_supported_auth_factors(proto_type);
        supported_auth_factors.push_back(*type);
      }
    }
  } else if (is_ephemeral_user) {
    // Use the credential verifier for the session to determine what types of
    // factors are configured.
    if (user_session) {
      for (const CredentialVerifier* verifier :
           user_session->GetCredentialVerifiers()) {
        if (IsPublicType(verifier->auth_factor_type())) {
          auto auth_factor_with_status = GetAuthFactorWithStatus(
              obfuscated_username, *user_policy_file_status,
              auth_factor_driver_manager_, verifier);
          if (auth_factor_with_status.has_value()) {
            *reply.add_configured_auth_factors_with_status() =
                std::move(*auth_factor_with_status);
          }
        }
      }
    }
    // Determine what auth factors are supported by going through the entire set
    // of auth factor types and checking each one.
    for (auto proto_type :
         PROTOBUF_ENUM_ALL_VALUES(user_data_auth::AuthFactorType)) {
      std::optional<AuthFactorType> type = AuthFactorTypeFromProto(proto_type);
      if (!type || !IsPublicType(*type)) {
        continue;
      }
      const AuthFactorDriver& factor_driver =
          auth_factor_driver_manager_->GetDriver(*type);
      if (factor_driver.IsLightAuthSupported(AuthIntent::kVerifyOnly)) {
        reply.add_supported_auth_factors(proto_type);
        supported_auth_factors.push_back(*type);
      }
    }
  }

  // For every supported auth factor type the user has, report the available
  // auth intents.
  for (AuthFactorType type : supported_auth_factors) {
    const AuthFactorDriver& factor_driver =
        auth_factor_driver_manager_->GetDriver(type);
    auto type_policy = GetAuthFactorPolicyFromUserPolicy(
        (*user_policy_file_status)->GetUserPolicy(), type);
    // Proto AuthIntentsForAuthFactorType assumes nothing is enabled if the type
    // policy is empty, but here the emptiness is just an indication of no
    // change to the default policy.
    if (type_policy.enabled_intents.empty() &&
        type_policy.disabled_intents.empty()) {
      SetAuthIntentsForAuthFactorType(type, factor_driver, std::nullopt,
                                      /*is_persistent_user=*/is_persistent_user,
                                      /*is_ephemeral_user=*/is_ephemeral_user,
                                      reply.add_auth_intents_for_types());
    } else {
      SetAuthIntentsForAuthFactorType(type, factor_driver, type_policy,
                                      /*is_persistent_user=*/is_persistent_user,
                                      /*is_ephemeral_user=*/is_ephemeral_user,
                                      reply.add_auth_intents_for_types());
    }
  }

  // TODO(b/247122507): Remove this with configured_auth_factor field once tast
  // test cleanup is done.
  for (auto configured_auth_factors_with_status :
       reply.configured_auth_factors_with_status()) {
    user_data_auth::AuthFactor auth_factor;
    auth_factor.CopyFrom(configured_auth_factors_with_status.auth_factor());
    *reply.add_configured_auth_factors() = std::move(auth_factor);
  }

  // Successfully completed, send the response with OK.
  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::ModifyAuthFactorIntents(
    user_data_auth::ModifyAuthFactorIntentsRequest request,
    OnDoneCallback<user_data_auth::ModifyAuthFactorIntentsReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotFoundInModifyAuthFactorIntents),
      CRYPTOHOME_ERR_LOC(
          kLocUserDataAuthSessionNotAuthInModifyAuthFactorIntents),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::ModifyAuthFactorIntentsWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::ModifyAuthFactorIntentsWithSession(
    user_data_auth::ModifyAuthFactorIntentsRequest request,
    OnDoneCallback<user_data_auth::ModifyAuthFactorIntentsReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::ModifyAuthFactorIntentsReply reply;
  std::optional<AuthFactorType> type = AuthFactorTypeFromProto(request.type());
  if (!type.has_value()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocAuthFactorTypeNotFoundInModifyAuthFactorIntents),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT));
    return;
  }
  auto user_policy_file_status =
      LoadUserPolicyFile(auth_session->obfuscated_username());
  if (!user_policy_file_status.ok()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocCouldntLoadUserPolicyFileInModifyAuthFactorIntents))
            .Wrap(std::move(user_policy_file_status).err_status()));
    return;
  }
  SerializedUserAuthFactorTypePolicy new_auth_factor_policy;
  std::set<AuthIntent> intents_for_auth_factor;
  for (int i = 0; i < request.intents_size(); i++) {
    auto auth_intent_from_proto = AuthIntentFromProto(request.intents(i));
    if (!auth_intent_from_proto.has_value()) {
      ReplyWithError(
          std::move(on_done), reply,
          MakeStatus<CryptohomeError>(
              CRYPTOHOME_ERR_LOC(
                  kLocCouldntConvertToAuthIntentInModifyAuthFactorIntents),
              ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                              PossibleAction::kReboot}),
              user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT));
      return;
    }
    intents_for_auth_factor.insert(*auth_intent_from_proto);
  }
  new_auth_factor_policy.type = SerializeAuthFactorType(*type);
  const AuthFactorDriver& driver =
      auth_factor_driver_manager_->GetDriver(*type);
  bool is_ephemeral_user = auth_session->ephemeral_user();

  // Any intent that is enabled should be both supported by the hardware and be
  // configurable.
  if (driver.IsSupportedByHardware()) {
    for (auto intent : intents_for_auth_factor) {
      if (driver.GetIntentConfigurability(intent) ==
          AuthFactorDriver::IntentConfigurability::kNotConfigurable) {
        continue;
      }
      if (is_ephemeral_user) {
        if (!driver.IsLightAuthSupported(intent)) {
          continue;
        }
      } else {
        if (!driver.IsLightAuthSupported(intent) &&
            !driver.IsFullAuthSupported(intent)) {
          continue;
        }
      }
      new_auth_factor_policy.enabled_intents.push_back(
          SerializeAuthIntent(intent));
    }
    for (AuthIntent intent : kAllAuthIntents) {
      // If the policy has not enabled a configurable intent explicitly, it
      // should be listed as disabled.
      if (intents_for_auth_factor.find(intent) ==
              intents_for_auth_factor.end() &&
          driver.GetIntentConfigurability(intent) !=
              AuthFactorDriver::IntentConfigurability::kNotConfigurable) {
        new_auth_factor_policy.disabled_intents.push_back(
            SerializeAuthIntent(intent));
      }
    }
  }
  std::optional<SerializedUserPolicy> user_policy =
      (*user_policy_file_status)->GetUserPolicy();
  SerializedUserPolicy new_policy;
  new_policy.auth_factor_type_policy.push_back(new_auth_factor_policy);
  // The new user policy should include the policy for all of the auth factors
  // except for the updated auth factor. The last policy for this auth factor
  // should be entirely discarded as the modify doesn't update the policy and
  // rather replaces it.
  if (user_policy.has_value()) {
    for (auto policy : user_policy->auth_factor_type_policy) {
      if (policy.type.has_value() &&
          *policy.type != SerializeAuthFactorType(*type)) {
        new_policy.auth_factor_type_policy.push_back(policy);
      }
    }
  }
  (*user_policy_file_status)->UpdateUserPolicy(new_policy);
  CryptohomeStatus user_policy_store_status =
      (*user_policy_file_status)->StoreInFile();
  if (!user_policy_store_status.ok()) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(
                kLocCouldntStoreUserPolicyFileInModifyAuthFactorIntents))
            .Wrap(std::move(user_policy_store_status).err_status()));
    return;
  }
  SetAuthIntentsForAuthFactorType(*type, driver, new_auth_factor_policy,
                                  /*is_persistent_user=*/!is_ephemeral_user,
                                  /*is_ephemeral_user=*/is_ephemeral_user,
                                  reply.mutable_auth_intents());
  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::GetAuthFactorExtendedInfo(
    user_data_auth::GetAuthFactorExtendedInfoRequest request,
    OnDoneCallback<user_data_auth::GetAuthFactorExtendedInfoReply> on_done) {
  AssertOnMountThread();

  user_data_auth::GetAuthFactorExtendedInfoReply reply;

  // Compute the account_id and obfuscated user name from the request.
  ObfuscatedUsername obfuscated_username =
      SanitizeUserName(GetAccountId(request.account_id()));

  // Try to find the relevant auth factor with the given label and convert it
  // into an auth factor proto.
  user_data_auth::AuthFactor auth_factor_proto;
  std::optional<AuthFactorType> auth_factor_type;
  for (const auto& [label, type] :
       auth_factor_manager_->ListAuthFactors(obfuscated_username)) {
    if (label == request.auth_factor_label()) {
      // Save the type.
      auth_factor_type = type;
      // Attempt to load the factor and then load it into the response.
      auto auth_factor = auth_factor_manager_->LoadAuthFactor(
          obfuscated_username, type, label);
      if (auth_factor.ok()) {
        const AuthFactorDriver& driver =
            auth_factor_driver_manager_->GetDriver(type);
        if (auto converted_to_proto =
                driver.ConvertToProto(label, auth_factor->metadata())) {
          auth_factor_proto = std::move(*converted_to_proto);
        }
      }
      // Stop searching because we found the factor with the requested label,
      // even if loading it or converting it into a proto failed.
      break;
    }
  }

  // If we at least found the type, also load any type-specific extended info.
  if (!auth_factor_type) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthFactorExtendedInfoTypeFailure),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_KEY_NOT_FOUND));
    return;
  }
  switch (*auth_factor_type) {
    case AuthFactorType::kCryptohomeRecovery: {
      if (!request.has_recovery_info_request()) {
        ReplyWithError(
            std::move(on_done), reply,
            MakeStatus<CryptohomeError>(
                CRYPTOHOME_ERR_LOC(
                    kLocUserDataAuthFactorExtendedInfoRecoveryIdFailure),
                ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
                user_data_auth::CryptohomeErrorCode::
                    CRYPTOHOME_ERROR_INVALID_ARGUMENT));
        return;
      }
      std::unique_ptr<cryptorecovery::RecoveryCryptoImpl> recovery =
          cryptorecovery::RecoveryCryptoImpl::Create(recovery_crypto_,
                                                     platform_);
      if (!recovery) {
        ReplyWithError(
            std::move(on_done), reply,
            MakeStatus<CryptohomeError>(
                CRYPTOHOME_ERR_LOC(
                    kLocUserDataAuthRecoveryObjectFailureGetRecoveryId),
                ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
                user_data_auth::CryptohomeErrorCode::
                    CRYPTOHOME_ERROR_RECOVERY_FATAL));
        return;
      }
      std::vector<std::string> recovery_ids = recovery->GetLastRecoveryIds(
          request.account_id(), request.recovery_info_request().max_depth());
      user_data_auth::RecoveryExtendedInfoReply recovery_reply;
      for (const std::string& recovery_id : recovery_ids) {
        recovery_reply.add_recovery_ids(recovery_id);
      }
      *reply.mutable_recovery_info_reply() = std::move(recovery_reply);
      break;
    }
    default: {
      LOG(WARNING) << AuthFactorTypeToString(*auth_factor_type)
                   << " factor type does not support extended info.";
    }
  }
  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::PrepareAuthFactor(
    user_data_auth::PrepareAuthFactorRequest request,
    OnDoneCallback<user_data_auth::PrepareAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthPrepareAuthFactorAuthSessionNotFound),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::PrepareAuthFactorWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::PrepareAuthFactorWithSession(
    user_data_auth::PrepareAuthFactorRequest request,
    OnDoneCallback<user_data_auth::PrepareAuthFactorReply> on_done,
    InUseAuthSession auth_session) {
  AuthSession* auth_session_ptr = auth_session.Get();
  auth_session_ptr->PrepareAuthFactor(
      request,
      base::BindOnce(
          [](InUseAuthSession auth_session, std::optional<AuthFactorType> type,
             OnDoneCallback<user_data_auth::PrepareAuthFactorReply> on_done,
             CryptohomeStatus status) {
            user_data_auth::PrepareAuthFactorReply reply;
            if (type) {
              if (AuthSession* auth_session_ptr = auth_session.Get()) {
                if (const PrepareOutput* prepare_output =
                        auth_session_ptr->GetFactorTypePrepareOutput(*type)) {
                  *reply.mutable_prepare_output() =
                      PrepareOutputToProto(*prepare_output);
                }
              }
            }
            ReplyWithError<user_data_auth::PrepareAuthFactorReply>(
                std::move(on_done), std::move(reply), std::move(status));
          },
          std::move(auth_session).BindForCallback(),
          AuthFactorTypeFromProto(request.auth_factor_type()),
          std::move(on_done)));
}

void UserDataAuth::TerminateAuthFactor(
    user_data_auth::TerminateAuthFactorRequest request,
    OnDoneCallback<user_data_auth::TerminateAuthFactorReply> on_done) {
  AssertOnMountThread();
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthTerminateAuthFactorNoAuthSession),
      std::move(request), std::move(on_done),
      base::BindOnce(
          [](user_data_auth::TerminateAuthFactorRequest request,
             OnDoneCallback<user_data_auth::TerminateAuthFactorReply> on_done,
             InUseAuthSession auth_session) {
            AuthSession* auth_session_ptr = auth_session.Get();
            auth_session_ptr->TerminateAuthFactor(
                request,
                base::BindOnce(
                    &ReplyWithStatus<user_data_auth::TerminateAuthFactorReply>,
                    std::move(auth_session).BindForCallback(),
                    std::move(on_done)));
          }));
}

void UserDataAuth::GetAuthSessionStatus(
    user_data_auth::GetAuthSessionStatusRequest request,
    OnDoneCallback<user_data_auth::GetAuthSessionStatusReply> on_done) {
  AssertOnMountThread();
  RunWithAuthSessionWhenAvailable(
      auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthGetAuthSessionStatusNoAuthSession),
      std::move(request), std::move(on_done),
      base::BindOnce(
          [](user_data_auth::GetAuthSessionStatusRequest request,
             OnDoneCallback<user_data_auth::GetAuthSessionStatusReply> on_done,
             InUseAuthSession auth_session) {
            user_data_auth::GetAuthSessionStatusReply reply;
            PopulateAuthSessionProperties(auth_session,
                                          reply.mutable_auth_properties());
            ReplyWithError(std::move(on_done), std::move(reply),
                           OkStatus<CryptohomeError>());
          }));
}

void UserDataAuth::LockFactorUntilReboot(
    user_data_auth::LockFactorUntilRebootRequest request,
    OnDoneCallback<user_data_auth::LockFactorUntilRebootReply> on_done) {
  AssertOnMountThread();
  user_data_auth::LockFactorUntilRebootReply reply;

  if (request.auth_factor_type() !=
      user_data_auth::AUTH_FACTOR_TYPE_CRYPTOHOME_RECOVERY) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthWrongFactorTypeInLockFactor),
            ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_NOT_IMPLEMENTED));
    return;
  }

  if (!platform_->FileExists(GetRecoveryFactorLockPath()) &&
      !platform_->TouchFileDurable(GetRecoveryFactorLockPath())) {
    ReplyWithError(
        std::move(on_done), reply,
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthTouchFailedInLockFactor),
            ErrorActionSet({PossibleAction::kRetry, PossibleAction::kReboot}),
            user_data_auth::CryptohomeErrorCode::
                CRYPTOHOME_ERROR_BACKING_STORE_FAILURE));
    return;
  }

  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::CreateVaultKeyset(
    user_data_auth::CreateVaultKeysetRequest request,
    OnDoneCallback<user_data_auth::CreateVaultKeysetReply> on_done) {
  user_data_auth::CreateVaultKeysetReply reply;

  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInCreateVaultKeyset),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInCreateVaultKeyset),
      std::move(request), std::move(on_done),
      base::BindOnce(
          [](CreateVaultKeysetRpcImpl* create_vault_keyset_impl,
             user_data_auth::CreateVaultKeysetRequest request,
             OnDoneCallback<user_data_auth::CreateVaultKeysetReply> on_done,
             InUseAuthSession auth_session) {
            AuthSession* auth_session_ptr = auth_session.Get();
            create_vault_keyset_impl->CreateVaultKeyset(
                request, *auth_session_ptr,
                base::BindOnce(
                    &ReplyWithStatus<user_data_auth::CreateVaultKeysetReply>,
                    std::move(auth_session).BindForCallback(),
                    std::move(on_done)));
          },
          create_vault_keyset_impl_.get()));
}

void UserDataAuth::RestoreDeviceKey(
    user_data_auth::RestoreDeviceKeyRequest request,
    OnDoneCallback<user_data_auth::RestoreDeviceKeyReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kRestoreKey, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInRestoreDeviceKey),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInRestoreDeviceKey),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::RestoreDeviceKeyWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::RestoreDeviceKeyWithSession(
    user_data_auth::RestoreDeviceKeyRequest request,
    OnDoneCallback<user_data_auth::RestoreDeviceKeyReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::RestoreDeviceKeyReply reply;
  if (auth_session->ephemeral_user()) {
    auto status = MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(
            kLocUserDataAuthEphemeralAuthSessionAttemptRestoreDeviceKey),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                        PossibleAction::kReboot}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    ReplyWithError(std::move(on_done), reply, status);
    return;
  }

  // Check the user is already mounted.
  UserSession* const session = sessions_->Find(auth_session->username());
  if (!session || !session->IsActive()) {
    auto status = MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthGetSessionFailedInRestoreDeviceKey),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState,
                        PossibleAction::kReboot}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    ReplyWithError(std::move(on_done), reply, status);
    return;
  }

  MountStatus mount_status =
      session->RestoreDeviceKey(auth_session->file_system_keyset());
  if (!mount_status.ok()) {
    RemoveInactiveUserSession(auth_session->username());
    auto status =
        MakeStatus<CryptohomeError>(
            CRYPTOHOME_ERR_LOC(kLocUserDataAuthRestoreDeviceKeyFailed))
            .Wrap(std::move(mount_status).err_status());
    ReplyWithError(std::move(on_done), reply, status);
    return;
  }

  // Read ID for the suspend request key was evicted on.
  std::string eviction_id_raw;
  int eviction_id = -1;
  if (!platform_->ReadFileToString(base::FilePath(kEncDeviceEvictedPath),
                                   &eviction_id_raw) ||
      !absl::SimpleAtoi(eviction_id_raw, &eviction_id)) {
    LOG(ERROR) << "Couldn't read " << kEncDeviceEvictedPath;
  }

  // Send a signal to power_manager to coordinate when to thaw processes
  // that touch the user's encrypted home directory and on what
  // suspend request the key was evicted.
  user_data_auth::EvictedKeyRestored key_restored_signal;
  key_restored_signal.set_eviction_id(eviction_id);
  signalling_intf_->SendEvictedKeyRestored(key_restored_signal);

  // Since key was restored, delete record of the suspend attempt key was
  // evicted on.
  if (!platform_->DeleteFile(base::FilePath(kEncDeviceEvictedPath))) {
    LOG(ERROR) << "Couldn't delete " << kEncDeviceEvictedPath;
  }

  ReplyWithError(std::move(on_done), reply, OkStatus<CryptohomeError>());
}

void UserDataAuth::MigrateLegacyFingerprints(
    user_data_auth::MigrateLegacyFingerprintsRequest request,
    OnDoneCallback<user_data_auth::MigrateLegacyFingerprintsReply> on_done) {
  AssertOnMountThread();
  RunWithAuthorizedAuthSessionWhenAvailable(
      AuthIntent::kDecrypt, auth_session_manager_,
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotFoundInMigrateFps),
      CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionNotAuthInMigrateFps),
      std::move(request), std::move(on_done),
      base::BindOnce(&UserDataAuth::MigrateLegacyFingerprintsWithSession,
                     base::Unretained(this)));
}

void UserDataAuth::MigrateLegacyFingerprintsWithSession(
    user_data_auth::MigrateLegacyFingerprintsRequest request,
    OnDoneCallback<user_data_auth::MigrateLegacyFingerprintsReply> on_done,
    InUseAuthSession auth_session) {
  user_data_auth::MigrateLegacyFingerprintsReply reply;
  if (auth_session->ephemeral_user()) {
    auto status = MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(
            kLocUserDataAuthEphemeralAuthSessionAttemptMigrateFps),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    ReplyWithError(std::move(on_done), reply, status);
    return;
  }

  // Only AuthSession for decrypt supports legacy fingerprint migration.
  auto* session_decrypt = auth_session->GetAuthForDecrypt();
  if (!session_decrypt) {
    auto status = MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthSessionDecryptFailedInMigrateFps),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    ReplyWithError(std::move(on_done), reply, status);
    return;
  }

  // Check the user is already mounted.
  UserSession* const session = sessions_->Find(auth_session->username());
  if (!session || !session->IsActive()) {
    auto status = MakeStatus<CryptohomeError>(
        CRYPTOHOME_ERR_LOC(kLocUserDataAuthGetSessionFailedInMigrateFps),
        ErrorActionSet({PossibleAction::kDevCheckUnexpectedState}),
        user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
    ReplyWithError(std::move(on_done), reply, status);
    return;
  }

  session_decrypt->MigrateLegacyFingerprints(base::BindOnce(
      &ReplyWithStatus<user_data_auth::MigrateLegacyFingerprintsReply>,
      std::move(auth_session).BindForCallback(), std::move(on_done)));
}

}  // namespace cryptohome
