blob: b55e50d62fd3454cb22c0d8627655d4aa9c6777f [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRYPTOHOME_KEYSET_MANAGEMENT_H_
#define CRYPTOHOME_KEYSET_MANAGEMENT_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include <brillo/secure_blob.h>
#include <cryptohome/proto_bindings/rpc.pb.h>
#include <cryptohome/proto_bindings/UserDataAuth.pb.h>
#include <dbus/cryptohome/dbus-constants.h>
#include "cryptohome/auth_blocks/auth_block_state.h"
#include "cryptohome/cleanup/user_oldest_activity_timestamp_manager.h"
#include "cryptohome/credentials.h"
#include "cryptohome/crypto.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/key_objects.h"
#include "cryptohome/platform.h"
#include "cryptohome/storage/homedirs.h"
#include "cryptohome/vault_keyset.h"
#include "cryptohome/vault_keyset_factory.h"
#include "storage/file_system_keyset.h"
namespace cryptohome {
class KeysetManagement {
public:
using DecryptVkCallback =
base::RepeatingCallback<bool(VaultKeyset*, CryptoError*)>;
using EncryptVkCallback = base::OnceCallback<bool(VaultKeyset* vk)>;
KeysetManagement() = default;
KeysetManagement(Platform* platform,
Crypto* crypto,
std::unique_ptr<VaultKeysetFactory> vault_keyset_factory);
virtual ~KeysetManagement() = default;
KeysetManagement(const KeysetManagement&) = delete;
KeysetManagement& operator=(const KeysetManagement&) = delete;
// Returns a list of present keyset indices for an obfuscated username.
// There is no guarantee the keysets are valid.
virtual bool GetVaultKeysets(const std::string& obfuscated,
std::vector<int>* keysets) const;
// Outputs a list of present keysets by label for a given obfuscated username.
// There is no guarantee the keysets are valid nor is the ordering guaranteed.
// Returns true on success, false if no keysets are found.
virtual bool GetVaultKeysetLabels(const std::string& obfuscated_username,
std::vector<std::string>* labels) const;
// Outputs a map of present keysets by label and the associate key data for a
// given obfuscated username. There is no guarantee the keysets are valid nor
// is the ordering guaranteed. Returns true on success, false if no keysets
// are found.
virtual bool GetVaultKeysetLabelsAndData(
const std::string& obfuscated_username,
std::map<std::string, KeyData>* key_label_data) const;
// Returns a VaultKeyset that matches the given obfuscated username and the
// key label. If the label is empty or if no matching keyset is found, NULL
// will be returned.
//
// The caller DOES take ownership of the returned VaultKeyset pointer.
// There is no guarantee the keyset is valid.
virtual std::unique_ptr<VaultKeyset> GetVaultKeyset(
const std::string& obfuscated_username,
const std::string& key_label) const;
// Returns true if the supplied Credentials are a valid (username, passkey)
// pair.
virtual bool AreCredentialsValid(const Credentials& credentials);
// Returns decrypted with |creds| keyset, or nullptr if none decryptable
// with the provided |creds| found and |error| will be populated with the
// partucular failure reason.
// NOTE: The LE Credential Keysets are only considered when the key label
// provided via |creds| is non-empty (b/202907485).
virtual std::unique_ptr<VaultKeyset> GetValidKeyset(const Credentials& creds,
MountError* error);
// Loads the vault keyset for the supplied obfuscated username and index.
// Returns true for success, false for failure.
std::unique_ptr<VaultKeyset> LoadVaultKeysetForUser(
const std::string& obfuscated_user, int index) const;
// Checks if the directory containing user keys exists.
virtual bool UserExists(const std::string& obfuscated_username);
// Adds initial keyset for the credentials and wraps the file system keyset
// provided. Returns the added keyset, or null on failure.
virtual std::unique_ptr<VaultKeyset> AddInitialKeyset(
const Credentials& credentials,
const FileSystemKeyset& file_system_keyset);
// This function should be called after successful authentication.
// Populate a value to |vault_keyset|'s reset seed if it is missing, but
// doesn't save.
virtual bool AddResetSeedIfMissing(VaultKeyset& vault_keyset);
// Adds randomly generated reset_seed to the vault keyset if |reset_seed_|
// doesn't have any value.
virtual CryptohomeErrorCode AddWrappedResetSeedIfMissing(
VaultKeyset* vault_keyset, const Credentials& credentials);
// Adds a new keyset to the given |vault_keyset| and persist to
// disk. This function assumes the user is already authenticated and their
// vault keyset with the existing credentials is unwrapped which should be
// inputted to this function to initialize a new vault keyset. Thus,
// GetValidKeyset() should be called prior to this function to authenticate
// with the existing credentials. New keyset is updated to have the key data
// from |new_credentials|. If |clobber| is true and there are no matching,
// labeled keys, then it does nothing; if there is an identically labeled key,
// it will overwrite it.
virtual CryptohomeErrorCode AddKeyset(const Credentials& new_credentials,
const VaultKeyset& vault_keyset,
bool clobber);
// Updates an existing |vault_keyset| with the new credentials. This function
// assumes the user is already authenticated and their |vault_keyset| with an
// existing credentials is unwrapped. New keyset is updated to have the key
// data from |new_credentials|, KeyBlobs from |VaultKeyset| and is wrapped by
// the secret in |new_credentials|.
virtual CryptohomeErrorCode UpdateKeyset(const Credentials& new_credentials,
const VaultKeyset& vault_keyset);
// Removes the keyset identified by |key_data|. The VaultKeyset backing
// |credentials| may be the same that |key_data| identifies.
virtual CryptohomeErrorCode RemoveKeyset(const Credentials& credentials,
const KeyData& key_data);
// Removes the keyset specified by |index| from the list for the user
// vault identified by its |obfuscated| username.
// The caller should check credentials if the call is user-sourced.
// TODO(wad,ellyjones) Determine a better keyset priotization and management
// scheme than just integer indices, like fingerprints.
virtual bool ForceRemoveKeyset(const std::string& obfuscated, int index);
// Allows a keyset to be moved to a different index assuming the index can be
// claimed for a given |obfuscated| username.
virtual bool MoveKeyset(const std::string& obfuscated, int src, int dst);
// Migrates the cryptohome vault keyset to a new one for the new credentials.
virtual bool Migrate(const VaultKeyset& old_vk, const Credentials& newcreds);
// Attempts to reset all LE credentials associated with a username, given
// a credential |cred|.
void ResetLECredentials(const std::optional<Credentials>& creds,
const std::optional<VaultKeyset>& validated_vk,
const std::string& obfuscated);
// Removes all LE credentials for a user with |obfuscated_username|.
virtual void RemoveLECredentials(const std::string& obfuscated_username);
// Returns the public mount pass key derived from username.
virtual brillo::SecureBlob GetPublicMountPassKey(
const std::string& account_id);
// Get timestamp from a legacy location.
// TODO(b/205759690, dlunev): can be removed after a stepping stone release.
virtual base::Time GetKeysetBoundTimestamp(const std::string& obfuscated);
// Remove legacy location for timestamp.
// TODO(b/205759690, dlunev): can be removed after a stepping stone release.
virtual void CleanupPerIndexTimestampFiles(const std::string& obfuscated);
// Checks whether the keyset is up to date (e.g. has correct encryption
// parameters, has all required fields populated etc.) and if not, updates
// and resaves the keyset.
virtual bool ReSaveKeysetIfNeeded(const Credentials& credentials,
VaultKeyset* keyset) const;
// Check if the vault keyset needs re-encryption.
virtual bool ShouldReSaveKeyset(VaultKeyset* vault_keyset) const;
// Record various metrics about all the VaultKeyset for a given user
// obfuscated
virtual void RecordAllVaultKeysetMetrics(const std::string& obfuscated) const;
// ========== KeysetManagement methods with KeyBlobs ===============
// Resaves the vault keyset with |key_blobs|, restoring on failure.
virtual bool ReSaveKeysetWithKeyBlobs(
VaultKeyset& vault_keyset,
KeyBlobs key_blobs,
std::unique_ptr<AuthBlockState> auth_state) const;
// Adds initial keyset for obfuscated username with |file_system_keyset|. Adds
// the key data given by |key_data| and challenge credentials info given by
// |challenge_credentials_keyset_info| to the created keyset. Wraps the keyset
// with |key_blobs| and persists to the disk.
virtual std::unique_ptr<VaultKeyset> AddInitialKeysetWithKeyBlobs(
const std::string& obfuscated_username,
const KeyData& key_data,
const SerializedVaultKeyset_SignatureChallengeInfo&
challenge_credentials_keyset_info,
const FileSystemKeyset& file_system_keyset,
KeyBlobs key_blobs,
std::unique_ptr<AuthBlockState> auth_state);
// Returns decrypted with |key_blobs| keyset, or nullptr if none decryptable
// with the provided |key_blobs|, |obfuscated_username| and |label| found.
// |error| will be populated with the partucular failure reason. NOTE: The LE
// Credential Keysets are only considered when the |label| provided is
// non-empty (b/202907485).
virtual std::unique_ptr<VaultKeyset> GetValidKeysetWithKeyBlobs(
const std::string& obfuscated_username,
KeyBlobs key_blobs,
const std::optional<std::string>& label,
MountError* error);
// Adds a new keyset to the given |vault_keyset| and persist to
// disk. This function assumes the user is already authenticated and their
// old vault keyset, |old_vault_keyset| is unwrapped to initialize a new vault
// keyset. Thus, GetValidKeyset() should be called prior to this function to
// authenticate with the existing credentials. New keyset is generated and the
// key data from |key_data_new| is added. New keyset is persisted to disk
// after wrapped by |key_blobs_new| as directed by |auth_state_new|. If
// |clobber| is true and there are no matching, labeled keys, then it does
// nothing; if there is an identically labeled key, it will overwrite it.
virtual CryptohomeErrorCode AddKeysetWithKeyBlobs(
const std::string& obfuscated_username_new,
const KeyData& key_data_new,
const VaultKeyset& vault_keyset_old,
KeyBlobs key_blobs_new,
std::unique_ptr<AuthBlockState> auth_state_new,
bool clobber);
// Encrypts and saves a keyset with the given |key_blobs|.
virtual CryptohomeErrorCode SaveKeysetWithKeyBlobs(
VaultKeyset& vault_keyset,
const KeyBlobs& key_blobs,
const AuthBlockState& auth_state);
// Updates an existing |vault_keyset| with the |key_data_new| from new user
// credentials. This function assumes the user is already authenticated and
// their |vault_keyset| with an existing credentials is unwrapped. New keyset
// is wrapped by the |key_blobs| passed, which should be derived from the new
// credentials.
virtual CryptohomeErrorCode UpdateKeysetWithKeyBlobs(
const std::string& obfuscated_username_new,
const KeyData& key_data_new,
const VaultKeyset& vault_keyset,
KeyBlobs key_blobs,
std::unique_ptr<AuthBlockState> auth_state);
private:
// Adds initial keyset for obfuscated username with |file_system_keyset|. Adds
// the key data given by |key_data| and challenge credentials info given by
// |challenge_credentials_keyset_info| to the created keyset. Wraps keyset
// with |encrypt_vk_callback| and persists to disk.
std::unique_ptr<VaultKeyset> AddInitialKeysetImpl(
const std::string& obfuscated_username,
const KeyData& key_data,
const SerializedVaultKeyset_SignatureChallengeInfo&
challenge_credentials_keyset_info,
const FileSystemKeyset& file_system_keyset,
EncryptVkCallback encrypt_vk_callback);
// Returns decrypted VaultKeyset for the obfuscated_username and label or
// nullptr if none decryptable.
std::unique_ptr<VaultKeyset> GetValidKeysetImpl(
const std::string& obfuscated_username,
const std::optional<std::string>& label,
DecryptVkCallback decrypt_vk_callback,
MountError* error);
// Generates a new keyset for |obfuscated_username_new| with |key_data_new|
// and the filesystem key from |vault_keyset_old| and persist to disk. If
// |clobber| is true and there are no matching, labeled keys, then it does
// nothing; if there is an identically labeled key, it will overwrite it.
CryptohomeErrorCode AddKeysetImpl(const std::string& obfuscated_username_new,
const KeyData& key_data_new,
const VaultKeyset& vault_keyset_old,
EncryptVkCallback encrypt_vk_callback,
bool clobber);
// Resaves the given |vault_keyset| with the credentials, restoring on error.
bool ReSaveKeyset(const Credentials& credentials,
VaultKeyset* vault_keyset) const;
// Implements the common functionality for resaving a keyset with restore on
// error.
bool ReSaveKeysetImpl(VaultKeyset& vault_keyset,
EncryptVkCallback encrypt_vk_callback) const;
// TODO(b/205759690, dlunev): can be removed after a stepping stone release.
base::Time GetPerIndexTimestampFileData(const std::string& obfuscated,
int index);
// Records various metrics about the VaultKeyset into the VaultKeysetMetrics
// struct.
bool RecordVaultKeysetMetrics(const VaultKeyset& vk,
VaultKeysetMetrics& keyset_metrics) const;
Platform* platform_;
Crypto* crypto_;
std::unique_ptr<VaultKeysetFactory> vault_keyset_factory_;
FRIEND_TEST(KeysetManagementTest, ReSaveOnLoadNoReSave);
FRIEND_TEST(KeysetManagementTest, ReSaveOnLoadTestRegularCreds);
FRIEND_TEST(KeysetManagementTest, ReSaveOnLoadTestLeCreds);
};
} // namespace cryptohome
#endif // CRYPTOHOME_KEYSET_MANAGEMENT_H_