blob: 000a581f1c7010fff12941b06bb8fc8db9f23bd6 [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.
#include "cryptohome/le_credential_manager.h"
#include <map>
#include <memory>
#include <vector>
#include "cryptohome/le_credential_backend.h"
#include "cryptohome/sign_in_hash_tree.h"
namespace cryptohome {
// Class containing all logic pertaining to management of Low Entropy(LE)
// credentials. The stated aim of this class should be the following:
// - Provide an interface to Set and Remove credentials in the underlying
// storage.
// - Provide an interface to verify a credential.
// This class contains a SignInHashTree object, which is used to store and
// maintain the credentials on disk.
// It also contains a pointer to a TPM object which will be able to invoke the
// necessary commands on the TPM side, for verification.
class LECredentialManagerImpl : public LECredentialManager {
explicit LECredentialManagerImpl(LECredentialBackend* le_backend,
const base::FilePath& le_basedir);
virtual ~LECredentialManagerImpl() {}
LECredError InsertCredential(const brillo::SecureBlob& le_secret,
const brillo::SecureBlob& he_secret,
const brillo::SecureBlob& reset_secret,
const DelaySchedule& delay_sched,
const ValidPcrCriteria& valid_pcr_criteria,
uint64_t* ret_label) override;
LECredError CheckCredential(const uint64_t& label,
const brillo::SecureBlob& le_secret,
brillo::SecureBlob* he_secret,
brillo::SecureBlob* reset_secret) override;
LECredError ResetCredential(const uint64_t& label,
const brillo::SecureBlob& reset_secret) override;
LECredError RemoveCredential(const uint64_t& label) override;
bool NeedsPcrBinding(const uint64_t& label) override;
// Returns the number of wrong authentication attempts done since the label
// was reset or created. Returns -1 if |label| is not present in the tree or
// the tree is corrupted.
int GetWrongAuthAttempts(const uint64_t& label) override;
// Since the CheckCredential() and ResetCredential() functions are very
// similar, this function combines the common parts of both the calls
// into a generic "check credential" function. The label to be checked
// is stored in |label|, the secret to be verified is in |secret|, the
// high entropy credential and reset secret which gets released on successful
// verification are stored in |he_secret| and |reset_secret|. A flag
// |is_le_secret| is used to signal whether the secret being checked is the LE
// secret (true) or the reset secret (false).
// Returns LE_CRED_SUCCESS on success.
// On failure, returns:
// - LE_CRED_ERROR_INVALID_LE_SECRET for incorrect LE authentication attempt.
// - LE_CRED_ERROR_INVALID_RESET_SECRET for incorrect reset secret.
// incorrect attempts).
// - LE_CRED_ERROR_HASH_TREE for error in hash tree.
// - LE_CRED_ERROR_INVALID_LABEL for invalid label.
// - LE_CRED_ERROR_INVALID_METADATA for invalid credential metadata.
// - LE_CRED_ERROR_PCR_NOT_MATCH if the PCR registers from TPM have unexpected
// values, in which case only reboot will allow this user to authenticate.
LECredError CheckSecret(const uint64_t& label,
const brillo::SecureBlob& secret,
brillo::SecureBlob* he_secret,
brillo::SecureBlob* reset_secret,
bool is_le_secret);
// Helper function to retrieve the credential metadata, MAC, and auxiliary
// hashes associated with a label |label| (stored in |cred_metadata|, |mac|
// and |h_aux| respectively). |metadata_lost| will denote whether the label
// contains valid metadata (false) or not (true).
// Returns LE_CRED_SUCCESS on success.
// On failure, returns:
// - LE_CRED_ERROR_INVALID_LABEL if the label provided doesn't exist.
// - LE_CRED_ERROR_HASH_TREE if there was hash tree error (possibly out of
// sync).
LECredError RetrieveLabelInfo(const SignInHashTree::Label& label,
std::vector<uint8_t>* cred_metadata,
std::vector<uint8_t>* mac,
std::vector<std::vector<uint8_t>>* h_aux,
bool* metadata_lost);
// Given a label, gets the list of auxiliary hashes for that label.
// On failure, returns an empty vector.
std::vector<std::vector<uint8_t>> GetAuxHashes(
const SignInHashTree::Label& label);
// Converts the error returned from LECredentialBackend to the equivalent
// LECredError.
LECredError ConvertTpmError(LECredBackendError err);
// Performs checks to ensure the SignInHashTree is in sync with the tree
// state in the LECredentialBackend. If there is an out-of-sync situation,
// this function also attempts to get the HashTree back in sync.
// Returns true on successful synchronization, and false on failure. On
// failure, |is_locked_| will be set to true, to prevent further
// operations during the class lifecycle.
bool Sync();
// Replays the InsertCredential operation using the information provided
// from the log entry from the LE credential backend.
// |label| denotes which label to perform the operation on,
// |log_root| is what the root hash should be after this operation is
// completed. It should directly be used from the log entry.
// |mac| is the MAC of the credential which has to be inserted.
// Returns true on success, false on failure.
// NOTE: A replayed insert is unusable and should be deleted after the replay
// is complete.
bool ReplayInsert(uint64_t label,
const std::vector<uint8_t>& log_root,
const std::vector<uint8_t>& mac);
// Replays the CheckCredential / ResetCredential operation using the
// information provided from the log entry from the LE credential
// backend.
// |label| denotes which credential label to perform the operation on.
// |log_root| is what the root hash should be after this operation is
// completed. It should directly be used from the log entry.
// Returns true on success, false on failure.
bool ReplayCheck(uint64_t label, const std::vector<uint8_t>& log_root);
// Resets the HashTree.
bool ReplayResetTree();
// Replays the RemoveCredential for |label| which is provided from
// the LE Backend Replay logs.
// Returns true on success, false otherwise.
bool ReplayRemove(uint64_t label);
// Replays all the log operations provided in |log|, and makes the
// corresponding updates to the HashTree.
bool ReplayLogEntries(const std::vector<LELogEntry>& log,
const std::vector<uint8_t>& disk_root_hash);
// Last resort flag which prevents any further Low Entropy operations from
// occurring, till the next time the class is instantiated.
// This is used in a situation where an operation succeeds on the TPM,
// but its on-disk counterpart fails. In this case, the mitigation strategy
// is as follows:
// - Prevent any further LE operations, to prevent disk and TPM from
// going further out of state, till next reboot.
// - Hope that on reboot, the problems causing disk failure don't recur,
// and the TPM replay log will enable the disk state to get in sync with
// the TPM again.
// We will collect UMA stats from the field and refine this strategy
// as required.
bool is_locked_;
// Pointer to an implementation of the LE Credential operations in TPM.
LECredentialBackend* le_tpm_backend_;
// In-memory copy of LEBackend's root hash value.
std::vector<uint8_t> root_hash_;
// Directory where all LE Credential related data is stored.
base::FilePath basedir_;
std::unique_ptr<SignInHashTree> hash_tree_;
} // namespace cryptohome