blob: 31c65d00bac4f208b2dd600ec3a26c07843b70da [file] [log] [blame]
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRYPTOHOME_AUTH_SESSION_H_
#define CRYPTOHOME_AUTH_SESSION_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <base/containers/flat_set.h>
#include <base/functional/callback.h>
#include <base/functional/callback_forward.h>
#include <base/memory/weak_ptr.h>
#include <base/timer/wall_clock_timer.h>
#include <base/unguessable_token.h>
#include <brillo/secure_blob.h>
#include <cryptohome/proto_bindings/auth_factor.pb.h>
#include <cryptohome/proto_bindings/rpc.pb.h>
#include <cryptohome/proto_bindings/recoverable_key_store.pb.h>
#include <cryptohome/proto_bindings/UserDataAuth.pb.h>
#include <libhwsec/structures/explicit_init.h>
#include <libhwsec-foundation/status/status_chain_or.h>
#include <libstorage/platform/platform.h>
#include "cryptohome/auth_blocks/auth_block_utility.h"
#include "cryptohome/auth_blocks/prepare_token.h"
#include "cryptohome/auth_factor/auth_factor.h"
#include "cryptohome/auth_factor/flatbuffer.h"
#include "cryptohome/auth_factor/manager.h"
#include "cryptohome/auth_factor/map.h"
#include "cryptohome/auth_factor/metadata.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_vault_keyset_converter.h"
#include "cryptohome/auth_intent.h"
#include "cryptohome/credential_verifier.h"
#include "cryptohome/crypto.h"
#include "cryptohome/error/cryptohome_error.h"
#include "cryptohome/features.h"
#include "cryptohome/flatbuffer_schemas/auth_block_state.h"
#include "cryptohome/flatbuffer_schemas/user_policy.h"
#include "cryptohome/key_objects.h"
#include "cryptohome/keyset_management.h"
#include "cryptohome/recoverable_key_store/backend_cert_provider.h"
#include "cryptohome/signalling.h"
#include "cryptohome/storage/file_system_keyset.h"
#include "cryptohome/user_secret_stash/decrypted.h"
#include "cryptohome/user_secret_stash/manager.h"
#include "cryptohome/user_secret_stash/storage.h"
#include "cryptohome/user_session/user_session_map.h"
#include "cryptohome/username.h"
#include "cryptohome/util/async_init.h"
namespace cryptohome {
using AuthFactorStatusUpdateCallback = base::RepeatingCallback<void(
user_data_auth::AuthFactorWithStatus, const std::string&)>;
// Helper function to return an empty auth factor type policy with the given
// type.
SerializedUserAuthFactorTypePolicy GetEmptyAuthFactorTypePolicy(
AuthFactorType type);
// This class starts a session for the user to authenticate with their
// credentials.
class AuthSession final {
private:
// Base class for all the AuthForXxx classes. Provides the standard
// boilerplate that every one of those classes supports:
// * They all provide kIntent static member of their AuthIntent
// * Their constructor takes a Passkey parameter that only AuthSession
// can construct, so that only AuthSession can create these
// * They can't be copied or moved.
//
// Each AuthIntent should have a corresponding subclass of this base that
// defines any AuthSession functions which REQUIRE the session to be
// authorized for this intent. The goal of this is to make it very difficult
// to accidentally write a bug where a function that requires authorization
// fails to check for it, by putting the function into a subobject that only
// gets created when the authorization happens.
template <AuthIntent intent>
class AuthForBase {
public:
class Passkey {
private:
friend class AuthSession;
Passkey() = default;
};
static constexpr AuthIntent kIntent = intent;
// Construct an AuthFor object for the given session. The passkey parameter
// is used just to restrict construction to classes and functions that can
// create the Passkey object (i.e. AuthSession).
AuthForBase(AuthSession& session, Passkey) : session_(&session) {}
AuthForBase(const AuthForBase&) = delete;
AuthForBase& operator=(const AuthForBase&) = delete;
protected:
AuthSession* session_;
};
public:
// Parameter struct used to specify all the base parameters of AuthSession.
// These parameters do not include the underlying interfaces that AuthSession
// depends on, which are defined below in a separate parameter struct.
struct Params {
hwsec::ExplicitInit<Username> username;
hwsec::ExplicitInit<bool> is_ephemeral_user;
hwsec::ExplicitInit<AuthIntent> intent;
std::unique_ptr<base::WallClockTimer> auth_factor_status_update_timer;
hwsec::ExplicitInit<bool> user_exists;
};
// Parameter struct used to supply all of the backing APIs that AuthSession
// depends on. All of these pointers must be valid for the entire lifetime of
// the AuthSession object.
struct BackingApis {
Crypto* crypto = nullptr;
libstorage::Platform* platform = nullptr;
UserSessionMap* user_session_map = nullptr;
KeysetManagement* keyset_management = nullptr;
AuthBlockUtility* auth_block_utility = nullptr;
AuthFactorDriverManager* auth_factor_driver_manager = nullptr;
AuthFactorManager* auth_factor_manager = nullptr;
UssStorage* user_secret_stash_storage = nullptr;
UssManager* user_secret_stash_manager = nullptr;
AsyncInitFeatures* features = nullptr;
AsyncInitPtr<SignallingInterface> signalling{nullptr};
AsyncInitPtr<RecoverableKeyStoreBackendCertProvider>
key_store_cert_provider{nullptr};
};
// Creates new auth session for account_id. This method returns a unique_ptr
// to the created AuthSession for the auth_session_manager to hold.
static std::unique_ptr<AuthSession> Create(Username username,
unsigned int flags,
AuthIntent intent,
BackingApis backing_apis);
// Construct an AuthSession initialized with all of the given state. This
// should generally only be used directly in testing; production code should
// prefer to call the Create factory function.
AuthSession(Params params, BackingApis backing_apis);
~AuthSession();
// Returns the full unhashed user name.
const Username& username() const { return username_; }
// Returns the obfuscated (sanitized) user name.
const ObfuscatedUsername& obfuscated_username() const {
return obfuscated_username_;
}
AuthIntent auth_intent() const { return auth_intent_; }
// Returns the token which is used to identify the current AuthSession.
const base::UnguessableToken& token() const { return token_; }
const std::string& serialized_token() const { return serialized_token_; }
// Returns the token which is used as the secondary identifier for the
// session. This is not used to identify the session internally in cryptohome
// but it is used in external APIs where the session needs to be identified
// without providing the ability to act on the session.
const base::UnguessableToken& public_token() const { return public_token_; }
const std::string& serialized_public_token() const {
return serialized_public_token_;
}
// Returns the intents that the AuthSession has been authorized for.
base::flat_set<AuthIntent> authorized_intents() const;
// Returns the file system keyset used to access the filesystem. This is set
// when the session gets into an authenticated state and so the caller must
// ensure that the AuthSession has been authenticated before accessing this.
const FileSystemKeyset& file_system_keyset() const;
// This function returns if the user existed when the auth session started.
bool user_exists() const { return user_exists_; }
// This function returns if the AuthSession is being setup for an ephemeral
// user.
bool ephemeral_user() const { return is_ephemeral_user_; }
// Returns the key data with which this AuthSession is authenticated with.
const KeyData& current_key_data() const { return key_data_; }
// Indicates if the session has a User Secret Stash enabled.
bool has_user_secret_stash() const { return decrypt_token_.has_value(); }
// Indicates if the session has migration to User Secret Stash enabled.
bool has_migrate_to_user_secret_stash() const {
return has_user_secret_stash();
}
// Indicates if there is a reset_secret in session's User Secret Stash for
// the given label.
inline bool HasResetSecretInUssForTesting(const std::string& label) const {
return decrypt_token_ &&
uss_manager_->GetDecrypted(*decrypt_token_).GetResetSecret(label);
}
// OnUserCreated is called when the user and their homedir are newly created.
// Must be called no more than once.
CryptohomeStatus OnUserCreated();
// Whether the AuthenticateAuthFactor request should be forced to perform full
// auth.
enum class ForceFullAuthFlag : bool {
kNone = false,
kForce = true,
};
// Flags to adjust behavior of the AuthenticateAuthFactor request.
struct AuthenticateAuthFactorFlags {
ForceFullAuthFlag force_full_auth;
};
// Packs necessary input parameters of AuthenticateAuthFactor request into a
// struct.
struct AuthenticateAuthFactorRequest {
std::vector<std::string> auth_factor_labels;
user_data_auth::AuthInput auth_input_proto;
AuthenticateAuthFactorFlags flags;
};
// Action that needs to be performed after an AuthenticateAuthFactor request
// is completed.
enum class PostAuthActionType {
kNone,
// Repeat the request with |repeat_request|. This will be used to reset the
// credential lockouts.
kRepeat,
// Terminate and prepare the auth factor again. This is used for the factors
// where an authentication attempts actually consumes the prepare token. To
// hide this implementation detail from Chrome, we need to implement it as a
// post-action.
kReprepare,
};
struct PostAuthAction {
PostAuthActionType action_type;
std::optional<AuthenticateAuthFactorRequest> repeat_request;
std::optional<user_data_auth::PrepareAuthFactorRequest> reprepare_request;
};
using AuthenticateAuthFactorCallback =
base::OnceCallback<void(const PostAuthAction&, CryptohomeStatus)>;
// Authenticate is called when the user wants to authenticate the current
// AuthSession via an auth factor. It may be called multiple times depending
// on errors or various steps involved in multi-factor authentication.
// Note: only USS users are supported currently.
void AuthenticateAuthFactor(
const AuthenticateAuthFactorRequest& request,
const SerializedUserAuthFactorTypePolicy& user_policy,
AuthenticateAuthFactorCallback callback);
// PrepareUserForRemoval is called to perform the necessary steps before
// removing a user, like preparing each auth factor for removal.
void PrepareUserForRemoval(base::OnceClosure on_finish);
// PrepareAuthFactor prepares an auth factor, e.g. fingerprint auth factor
// which is not directly associated with a knowledge factor.
void PrepareAuthFactor(
const user_data_auth::PrepareAuthFactorRequest& request,
StatusCallback on_done);
// TerminatesAuthFactor stops an async auth factor, e.g. fingerprint auth
// factor.
void TerminateAuthFactor(
const user_data_auth::TerminateAuthFactorRequest& request,
StatusCallback on_done);
// This function is used to reset the attempt count for a low entropy
// credential. Currently, this resets all low entropy credentials both
// stored in USS and VK.
void ResetLECredentials();
// Subobjects that implement operations that require the session to be
// authforized for a specific intent. While these are technically classes they
// are not really intended to be used as independent types. Instead it is
// best to think of them as sets of additional AuthSession functions with a
// specific precondition, "must be authorized for intent X".
//
// For consistency we define a class (AuthForXxx) and function (GetAuthForXxx)
// for each intent, although some of them are just empty stubs because the
// authorization opens up no additional operations. The GetAuthForXxx are
// similar to an "is authorized for Xxx" check except that instead of
// returning a bool the return either null (not authorized) or not null
// (authorized). If not null the returned objects have the same lifetime as
// the AuthSession object itself.
// AuthForDecrypt: operations that require AuthIntent::kDecrypt.
class AuthForDecrypt : public AuthForBase<AuthIntent::kDecrypt> {
public:
using AuthForBase::AuthForBase;
// Add a new auth factor from the given request.
void AddAuthFactor(const user_data_auth::AddAuthFactorRequest& request,
StatusCallback on_done);
// Update an existing auth factor from the given request.
void UpdateAuthFactor(
const user_data_auth::UpdateAuthFactorRequest& request,
StatusCallback on_done);
// Update only the metadata for an auth factor without changing the
// credentials themselves.
void UpdateAuthFactorMetadata(
const user_data_auth::UpdateAuthFactorMetadataRequest request,
StatusCallback on_done);
// Relabel an auth factor as specified by the given request.
void RelabelAuthFactor(
const user_data_auth::RelabelAuthFactorRequest& request,
StatusCallback on_done);
// Replace an auth factor as specified by the given request.
void ReplaceAuthFactor(
const user_data_auth::ReplaceAuthFactorRequest& request,
StatusCallback on_done);
// Remove an auth factor specified by the given request.
void RemoveAuthFactor(
const user_data_auth::RemoveAuthFactorRequest& request,
StatusCallback on_done);
// Prepares an auth factor type for the add purpose.
void PrepareAuthFactorForAdd(AuthFactorType auth_factor_type,
StatusCallback on_done);
private:
// Special case for relabel of an ephemeral user's factor.
void RelabelAuthFactorEphemeral(
const user_data_auth::RelabelAuthFactorRequest& request,
StatusCallback on_done);
// Special case for replace of an ephemeral user's factor.
void ReplaceAuthFactorEphemeral(
const user_data_auth::ReplaceAuthFactorRequest& request,
StatusCallback on_done);
// After successful creation of a replacement factor, swap it into USS as a
// replacement for the old factor. Designed to be bindable into an
// AuthBlock::CreateCallback.
void ReplaceAuthFactorIntoUss(
AuthFactor original_auth_factor,
AuthInput auth_input,
AuthFactorType auth_factor_type,
std::string auth_factor_label,
AuthFactorMetadata auth_factor_metadata,
std::unique_ptr<AuthSessionPerformanceTimer> perf_timer,
StatusCallback on_done,
CryptohomeStatus error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// Creates AuthInput for preparing an auth factor type for adding.
// As in this case the auth factor hasn't been decided yet, the AuthInput
// will typically be simpler than Add and Authenticate cases, and derivable
// from solely the |auth_factor_type|.
CryptohomeStatusOr<AuthInput> CreateAuthInputForPrepareForAdd(
AuthFactorType auth_factor_type);
// The last member, to invalidate weak references first on destruction.
base::WeakPtrFactory<AuthForDecrypt> weak_factory_{this};
};
friend class AuthForDecrypt;
AuthForDecrypt* GetAuthForDecrypt();
// AuthForXxx classes for intents which don't add any new operations. These
// classes are just simple stubs of AuthForBase that don't really do anything
// other than acting as indicators that the session is authorized for a
// specific intent, but we still define them this way for consistency. This
// allows most of the auth intent handling code to be written generically.
class AuthForVerifyOnly : public AuthForBase<AuthIntent::kVerifyOnly> {
public:
using AuthForBase::AuthForBase;
};
friend class AuthForVerifyOnly;
AuthForVerifyOnly* GetAuthForVerifyOnly();
class AuthForWebAuthn : public AuthForBase<AuthIntent::kWebAuthn> {
public:
using AuthForBase::AuthForBase;
};
friend class AuthForWebAuthn;
AuthForWebAuthn* GetAuthForWebAuthn();
// Generates a payload that will be sent to the server for cryptohome recovery
// AuthFactor authentication. GetRecoveryRequest saves data in the
// AuthSession state. This call is required before the AuthenticateAuthFactor
// call for cryptohome recovery AuthFactor.
void GetRecoveryRequest(
user_data_auth::GetRecoveryRequestRequest request,
base::OnceCallback<void(const user_data_auth::GetRecoveryRequestReply&)>
on_done);
// OnMigrationUssCreated is the callback function to be called after
// migration secret is generated and added to UserSecretStash during the
// AuthenticateViaVaultKeysetAndMigrateToUss() operation.
void OnMigrationUssCreated(
AuthBlockType auth_block_type,
AuthFactorType auth_factor_type,
const AuthFactorMetadata& auth_factor_metadata,
const AuthInput& auth_input,
CryptohomeStatus pre_migration_status,
StatusCallback on_done,
std::optional<UssManager::DecryptToken> loaded_token);
// OnMigrationUssCreatedForUpdate is the callback function to be called after
// migration secret is generated and added to UserSecretStash during the
// MigrateToUssDuringUpdateVaultKeyset() operation.
void OnMigrationUssCreatedForUpdate(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const AuthInput& auth_input,
StatusCallback on_done,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_state,
std::optional<UssManager::DecryptToken> loaded_token);
// Sets |vault_keyset_| for testing purpose.
void set_vault_keyset_for_testing(std::unique_ptr<VaultKeyset> value) {
vault_keyset_ = std::move(value);
}
// Static function which returns a serialized token in a vector format. The
// token is serialized into two uint64_t values which are stored in string of
// size 16 bytes. The first 8 bytes represent the high value of the serialized
// token, the next 8 represent the low value of the serialized token.
static std::optional<std::string> GetSerializedStringFromToken(
const base::UnguessableToken& token);
// Static function which returns UnguessableToken object after deconstructing
// the string formed in GetSerializedStringFromToken.
static std::optional<base::UnguessableToken> GetTokenFromSerializedString(
const std::string& serialized_token);
// Get the hibernate secret, derived from the file system keyset.
std::unique_ptr<brillo::SecureBlob> GetHibernateSecret();
// Add a callback to call when the AuthSession is authenticated. This callback
// is triggered immediately if the session is already authenticated.
void AddOnAuthCallback(base::OnceClosure on_auth);
// Send the auth factor status update signal and also set the timer for the
// next signal based on |kAuthFactorStatusUpdateDelay|.
void SendAuthFactorStatusUpdateSignal();
// Adds AuthFactor to the auth factor map, registered as a VaultKeyset backed
// factor. This functionality is only used by the cryptohome-test-tool and
// through UserDataAuth::CreateVaultKeyset() for testing purposes.
void RegisterVaultKeysetAuthFactor(AuthFactor auth_factor);
// Cancels the execution of any outstanding callbacks bound to this session.
// The can be used to "time out" an outstanding async operation that the
// session is executing.
void CancelAllOutstandingAsyncCallbacks();
private:
// Helper to get a reference to the AuthFactorMap for this session's user.
AuthFactorMap& GetAuthFactorMap();
// Emits a debug log message with this Auth Session's initial state.
void RecordAuthSessionStart(const AuthFactorMap& auth_factor_map) const;
// Switches the state to authorize the specified intents. Starts or restarts
// the timer when applicable.
void SetAuthorizedForIntents(
base::flat_set<AuthIntent> new_authorized_intents);
// Sets the auth session as fully authenticated by the given factor type. What
// specific intents the session is authorized for depends on the factor type.
void SetAuthorizedForFullAuthIntents(
AuthFactorType auth_factor_type,
const SerializedUserAuthFactorTypePolicy& user_policy);
// Converts the D-Bus AuthInput proto into the C++ struct. Returns nullopt on
// failure.
CryptohomeStatusOr<AuthInput> CreateAuthInputForAuthentication(
const user_data_auth::AuthInput& auth_input_proto);
// Same as above, but additionally sets extra fields for resettable factors.
// Can also be supplied with an already constructed AuthInput instead of the
// raw proto, for cases where you need to construct both and don't want to
// redo the same work.
CryptohomeStatusOr<AuthInput> CreateAuthInputForAdding(
const user_data_auth::AuthInput& auth_input_proto,
AuthFactorType auth_factor_type);
CryptohomeStatusOr<AuthInput> CreateAuthInputForAdding(
AuthInput auth_input, AuthFactorType auth_factor_type);
// Creates AuthInput for migration from an AuthInput by adding `reset_secret`
// if needed. If this is called during the AuthenticateAuthFactor, after the
// successful authentication of the PIN factor, reset secret is obtained
// directly from the decrypted PIN VaultKeyset. If this is called during the
// UpdateAuthFactor, when AuthSession has a decrypted password VaultKesyet
// available, |reset_secret| is derived from the |reset_seed| on the
// password VaultKeyset. In each case a new backend pinweaver node is created.
CryptohomeStatusOr<AuthInput> CreateAuthInputForMigration(
const AuthInput& auth_input, AuthFactorType auth_factor_type);
// Creates AuthInput for selecting the correct auth factor to be used for
// authentication. As in this case the auth factor hasn't been decided yet,
// the AuthInput will typically be simpler than Add and Authenticate cases,
// and derivable from solely the |auth_factor_type|.
CryptohomeStatusOr<AuthInput> CreateAuthInputForSelectFactor(
AuthFactorType auth_factor_type);
// Creates AuthInput for preparing an auth factor type for authentication.
// As in this case the auth factor hasn't been decided yet, the AuthInput will
// typically be simpler than Add and Authenticate cases, and derivable from
// solely the |auth_factor_type|.
CryptohomeStatusOr<AuthInput> CreateAuthInputForPrepareForAuth(
AuthFactorType auth_factor_type);
// This function attempts to add verifier for the given label based on the
// AuthInput. If it succeeds it will return a pointer to the verifier.
// Otherwise it will return null.
CredentialVerifier* AddCredentialVerifier(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthInput& auth_input,
const AuthFactorMetadata& auth_factor_metadata);
// Helper function to update a keyset on disk on KeyBlobs generated. If update
// succeeds |vault_keyset_| is also updated. Failure doesn't return error and
// doesn't block authentication operations.
void ResaveKeysetOnKeyBlobsGenerated(
VaultKeyset updated_vault_keyset,
CryptohomeStatus error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// Updates the secret of an AuthFactor backed by a VaultKeyset and migrates it
// to UserSecretStash. Failures during this operation fails to both update and
// migrate the factor.
void MigrateToUssDuringUpdateVaultKeyset(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const KeyData& key_data,
const AuthInput& auth_input,
StatusCallback on_done,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_state);
// Persists key blocks for a new secret to the USS and onto disk. Upon
// completion the |on_done| callback will be called. Designed to be used in
// conjunction with an async CreateKeyBlobs call by binding all of the
// initial parameters to make an AuthBlock::CreateCallback.
void PersistAuthFactorToUserSecretStash(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const AuthInput& auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
StatusCallback on_done,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// Persists from a migrated VaultKeyset AuthFactor and USS key block. Upon
// completion the |on_done| callback will be called with the pre-migration
// state.
void PersistAuthFactorToUserSecretStashOnMigration(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const AuthInput& auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
StatusCallback on_done,
CryptohomeStatus pre_migration_status,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// The implementation function to persists an AuthFactor and a USS key
// block for a new secret.
CryptohomeStatus PersistAuthFactorToUserSecretStashImpl(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const AuthInput& auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// Migrates the reset secret for a PIN factor from VaultKeysets to
// UserSecretStash by calculating it from |reset_seed| of the authenticated
// VaultKeyset and the |reset_salt| of the Pinweaver VaultKeysets and adding
// to USS in memory.
bool MigrateResetSecretToUss();
// Process the completion of a verify-only authentication attempt. The
// |on_done| callback will be called after the results of the verification are
// processed. This takes |auth_factor_type| parameter because it needs to
// determine whether the factor can be used for resetting credentials.
// Designed to be used in conjunction with CredentialVerifier::Verify as the
// CryptohomeStatusCallback.
void CompleteVerifyOnlyAuthentication(
AuthenticateAuthFactorCallback on_done,
AuthenticateAuthFactorRequest original_request,
AuthFactorType auth_factor_type,
CryptohomeStatus error);
// Add the given auth factor to an ongoing transaction.
CryptohomeStatus AddAuthFactorToUssTransaction(
AuthFactor& auth_factor,
const KeyBlobs& key_blobs,
DecryptedUss::Transaction& transaction);
// Returns the callback function to update and AuthFactor for the right key
// store type.
AuthBlock::CreateCallback GetUpdateAuthFactorCallback(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const KeyData& key_data,
const AuthInput& auth_input,
const AuthFactorStorageType auth_factor_storage_type,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
StatusCallback on_done);
// Adds a credential verifier for the ephemeral user session.
void AddAuthFactorForEphemeral(AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthInput& auth_input,
const AuthFactorMetadata& auth_factor_metadata,
StatusCallback on_done);
// Loads and decrypts the USS payload with |auth_factor| using the
// given KeyBlobs. Designed to be used in conjunction with an async
// DeriveKeyBlobs call by binding all of the initial parameters to make an
// AuthBlock::DeriveCallback.
void LoadUSSMainKeyAndFsKeyset(
const AuthFactor& auth_factor,
const AuthInput& auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
const SerializedUserAuthFactorTypePolicy& user_policy,
StatusCallback on_done,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::optional<AuthBlock::SuggestedAction> suggested_action);
// This function is used after a load to re-create an auth factor. It is
// generally used after a post-authenticate load, when the key derivation
// suggests that the factor needs to be recreated.
void RecreateUssAuthFactor(AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
AuthInput auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
CryptohomeStatus original_status,
StatusCallback on_done);
// This function is used to reset the attempt count and expiration
// for rate-limiters. Normally credentials guarded by rate-limiters will never
// be locked, but we still check them to see if they're accidentally locked.
// In that case, the reset secret is the same as the rate-limiter's.
void ResetRateLimiterCredentials();
// Whether there are some credentials that can be reset after a full auth.
bool NeedsFullAuthForReset();
// Authenticate the user with the single given auth factor. Additional
// parameters are provided to aid legacy vault keyset authentication and
// migration.
void AuthenticateViaSingleFactor(
const AuthFactorType& request_auth_factor_type,
const std::string& auth_factor_label,
const AuthInput& auth_input,
const AuthFactorMetadata& metadata,
const AuthFactorMap::ValueView& stored_auth_factor,
const SerializedUserAuthFactorTypePolicy& user_policy,
StatusCallback on_done);
// Authenticates the user using USS with the |auth_factor_label|, |auth_input|
// and the |auth_factor|.
void AuthenticateViaUserSecretStash(
const std::string& auth_factor_label,
const AuthInput auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
const AuthFactor& auth_factor,
const SerializedUserAuthFactorTypePolicy& user_policy,
StatusCallback on_done);
// Authenticates the user using VaultKeysets with the given |auth_input|.
void AuthenticateViaVaultKeysetAndMigrateToUss(
AuthFactorType request_auth_factor_type,
const std::string& key_label,
const AuthInput& auth_input,
const AuthFactorMetadata& metadata,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
const SerializedUserAuthFactorTypePolicy& user_policy,
StatusCallback on_done);
// Authenticates the user using the selected |auth_factor|. Used when the
// auth factor type takes multiple labels during authentication, and used as
// the callback for AuthBlockUtility::SelectAuthFactorWithAuthBlock.
void AuthenticateViaSelectedAuthFactor(
const SerializedUserAuthFactorTypePolicy& user_policy,
StatusCallback on_done,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
CryptohomeStatus callback_error,
std::optional<AuthInput> auth_input,
std::optional<AuthFactor> auth_factor);
// Fetches a valid VaultKeyset for |obfuscated_username_| that matches the
// label provided by key_data_.label(). The VaultKeyset is loaded and
// initialized into |vault_keyset_| through
// KeysetManagement::GetValidKeyset(). This function is needed for
// processing callback results in an asynchronous manner through the |on_done|
// callback.
void LoadVaultKeysetAndFsKeys(
AuthFactorType request_auth_factor_type,
const AuthInput& auth_input,
AuthBlockType auth_block_type,
const AuthFactorMetadata& metadata,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
const SerializedUserAuthFactorTypePolicy& user_policy,
StatusCallback on_done,
CryptohomeStatus error,
std::unique_ptr<KeyBlobs> key_blobs,
std::optional<AuthBlock::SuggestedAction> suggested_action);
// Updates, wraps and resaves |vault_keyset_| and restores on failure.
// |user_input| is needed to generate the AuthInput used for key blob creation
// to wrap the updated keyset.
AuthBlockType ResaveVaultKeysetIfNeeded(
const std::optional<brillo::SecureBlob> user_input,
AuthBlockType auth_block_type);
// Removes the key block with the provided `auth_factor_label` from the USS
// and removes the `auth_factor` from disk.
void RemoveAuthFactorViaUserSecretStash(const std::string& auth_factor_label,
const AuthFactor& auth_factor,
StatusCallback on_done);
// Removes the auth factor from the in-memory map, the existing keyset and
// verifier indexed by the `auth_factor_label`.
void ClearAuthFactorInMemoryObjects(
const std::string& auth_factor_label,
const AuthFactorMap::ValueView& stored_auth_factor,
const base::TimeTicks& remove_timer_start,
StatusCallback on_done,
CryptohomeStatus status);
// Re-persists the USS and removes in memory objects related to the
// removed auth factor.
void ResaveUssWithFactorRemoved(const std::string& auth_factor_label,
const AuthFactor& auth_factor,
StatusCallback on_done,
CryptohomeStatus status);
// Creates a new per-credential secret, updates the secret in the USS and
// updates the auth block state on disk.
void UpdateAuthFactorViaUserSecretStash(
AuthFactorType auth_factor_type,
const std::string& auth_factor_label,
const AuthFactorMetadata& auth_factor_metadata,
const AuthInput& auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
StatusCallback on_done,
CryptohomeStatus callback_error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// Persists the updated USS and
// re-creates the related credential verifier if applicable.
void ResaveUssWithFactorUpdated(AuthFactorType auth_factor_type,
AuthFactor auth_factor,
std::unique_ptr<KeyBlobs> key_blobs,
const AuthInput& auth_input,
std::unique_ptr<AuthSessionPerformanceTimer>
auth_session_performance_timer,
StatusCallback on_done,
CryptohomeStatus status);
// Handles the completion of an async PrepareAuthFactor call. Captures the
// token and forwards the result to the given status callback.
void OnPrepareAuthFactorDone(
StatusCallback on_done,
CryptohomeStatusOr<std::unique_ptr<PreparedAuthFactorToken>> token);
// Prepares the WebAuthn secret using file_system_keyset.
CryptohomeStatus PrepareWebAuthnSecret();
// Prepares the chaps key using file_system_keyset.
CryptohomeStatus PrepareChapsKey();
// RemoveRateLimiters remove all rate-limiter leaves in the UserMetadata. This
// doesn't leave the USS with a consistent state, and should only be called
// during PrepareUserForRemoval.
void RemoveRateLimiters();
// Calls |AuthBlockUtility::CreateKeyBlobsWithAuthBlock|, and creates the
// rest of the common (non-AuthBlockType-specific) fields of the
// AuthBlockState after it returns.
void CreateAuthBlockStateAndKeyBlobs(
AuthFactorType auth_factor_type,
AuthBlockType auth_block_type,
const AuthInput& auth_input,
const AuthFactorMetadata& auth_factor_metadata,
AuthBlock::CreateCallback create_callback);
// Used as a callback for |CreateAuthBlockStateAndKeyBlobs|. Creates the
// rest of the common (non-AuthBlockType-specific) fields of the
// AuthBlockState after it returns.
void CreateCommonAuthBlockState(
AuthFactorType auth_factor_type,
const AuthInput& auth_input,
const AuthFactorMetadata& auth_factor_metadata,
AuthBlock::CreateCallback create_callback,
CryptohomeStatus error,
std::unique_ptr<KeyBlobs> key_blobs,
std::unique_ptr<AuthBlockState> auth_block_state);
// Create the recoverable key store auth block state for the auth factor.
CryptohomeStatus CreateRecoverableKeyStore(
AuthFactorType auth_factor_type,
KnowledgeFactorType knowledge_factor_type,
const AuthFactorMetadata& auth_factor_metadata,
AuthInput auth_input,
AuthBlockState& auth_block_state);
// Check whether the recoverable key store state of |auth_factor| is outdated,
// and update it if so.
CryptohomeStatus MaybeUpdateRecoverableKeyStore(
const AuthFactor& auth_factor,
KnowledgeFactorType knowledge_factor_type,
AuthInput auth_input);
Username username_;
ObfuscatedUsername obfuscated_username_;
// Is the user of this session ephemeral?
const bool is_ephemeral_user_;
// The intent this session was started for.
const AuthIntent auth_intent_;
// AuthFor objects representing which intents the session is authorized for.
// These are null when the session is not authorized.
//
// Once a session is authorized for a specific intent that
// authorization cannot be cleared as clients may have references to the
// AuthFor object. In other words, intents cannot be "deauthorized".
std::optional<AuthForDecrypt> auth_for_decrypt_;
std::optional<AuthForVerifyOnly> auth_for_verify_only_;
std::optional<AuthForWebAuthn> auth_for_web_authn_;
// The wall clock timer object to send AuthFactor status update periodically.
std::unique_ptr<base::WallClockTimer> auth_factor_status_update_timer_;
base::TimeTicks auth_session_creation_time_;
base::TimeTicks authenticated_time_;
// Callbacks to be triggered when authentication occurs.
std::vector<base::OnceClosure> on_auth_;
// The USS storage and manager. These are used to access the USS.
UserUssStorage uss_storage_;
UssManager* uss_manager_;
// The decrypted USS token, set if the session has successfully completed a
// USS decryption.
std::optional<UssManager::DecryptToken> decrypt_token_;
Crypto* const crypto_;
libstorage::Platform* const platform_;
// The user session map and a verifier forwarder associated with it.
UserSessionMap* const user_session_map_;
UserSessionMap::VerifierForwarder verifier_forwarder_;
// TODO(crbug.com/1171024): Change KeysetManagement to use AuthBlock.
KeysetManagement* const keyset_management_;
AuthBlockUtility* const auth_block_utility_;
AuthFactorDriverManager* const auth_factor_driver_manager_;
AuthFactorManager* const auth_factor_manager_;
AsyncInitFeatures* const features_;
AsyncInitPtr<SignallingInterface> signalling_;
AsyncInitPtr<RecoverableKeyStoreBackendCertProvider> key_store_cert_provider_;
// A stateless object to convert AuthFactor API to VaultKeyset KeyData and
// VaultKeysets to AuthFactor API.
AuthFactorVaultKeysetConverter converter_;
// Tokens (and their serialized forms) used to identify the session.
const base::UnguessableToken token_;
const std::string serialized_token_;
const base::UnguessableToken public_token_;
const std::string serialized_public_token_;
// Used to decrypt/ encrypt & store credentials.
std::unique_ptr<VaultKeyset> vault_keyset_;
// Used to store key meta data.
KeyData key_data_;
// FileSystemKeyset is needed by cryptohome to mount a user.
std::optional<FileSystemKeyset> file_system_keyset_;
// Whether the user existed at the time this object was constructed.
bool user_exists_;
// Key used by AuthenticateAuthFactor for cryptohome recovery AuthFactor.
// It's set only after GetRecoveryRequest() call, and is std::nullopt in other
// cases.
std::optional<brillo::Blob> cryptohome_recovery_ephemeral_pub_key_;
// Tokens from active auth factors, keyed off of the token's auth factor type.
std::map<AuthFactorType, std::unique_ptr<PreparedAuthFactorToken>>
active_auth_factor_tokens_;
// Weak factory for creating weak pointers to |this| for timed tasks.
base::WeakPtrFactory<AuthSession> weak_factory_for_timed_tasks_{this};
// Weak factory for creating "normal" weak pointers to |this|. Tasks bound to
// these pointers will be cancelled by CancelAllOutstandingAsyncCallbacks.
base::WeakPtrFactory<AuthSession> weak_factory_{this};
};
} // namespace cryptohome
#endif // CRYPTOHOME_AUTH_SESSION_H_