blob: 046a95f5cbb661544f392d9422b5be68e685f241 [file] [log] [blame]
// Copyright 2012 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Lockbox - class for storing tamper-evident data blobs.
#ifndef CRYPTOHOME_LOCKBOX_H_
#define CRYPTOHOME_LOCKBOX_H_
#include <memory>
#include <base/strings/string_util.h>
#include <brillo/secure_blob.h>
#include <libhwsec/frontend/cryptohome/frontend.h>
#include <libstorage/platform/platform.h>
#include <openssl/sha.h>
namespace cryptohome {
class LockboxContents;
enum class LockboxError {
kNvramInvalid,
kTpmUnavailable,
kTpmError, // Transient or unknown TPM error.
};
// Enable LockboxError to be used in LOG output.
std::ostream& operator<<(std::ostream& out, LockboxError error);
// Lockbox stores a blob of data in a tamper-evident manner.
//
// This class provides system integration for supporting tamper-evident
// storage using the TPM NVRAM locking and restricted TPM ownership to
// ensure that a data blob stored on disk has not been tampered with to
// the degree that can be cryptographically assured.
//
// Lockbox is not thread-safe and should not be accessed in parallel.
//
// A normal usage flow for Lockbox would be something as follows:
//
// Initializing new data against a lockbox (except with error checking :)
// Lockbox lockbox(hwsec, hwsec::Space::kInstallAttributes);
// LockboxError error;
// lockbox->Create(&error);
// lockbox->Store(mah_locked_data, &error);
//
// Verifying data is performed via class |LockboxContents|.
class Lockbox {
public:
// Populates the basic internal state of the Lockbox.
//
// Parameters
// - hwsec: a required pointer to hwsec object.
// - space: the space for lockbox.
Lockbox(const hwsec::CryptohomeFrontend* hwsec, hwsec::Space space);
Lockbox(const Lockbox&) = delete;
Lockbox& operator=(const Lockbox&) = delete;
virtual ~Lockbox() = default;
// Sets up the backend state needed for this lockbox.
//
// Instantiates a new TPM NVRAM index lockable bWriteDefine to store
// the hash and blob size of the data to lock away.
//
// Parameters
// - error: will contain the LockboxError if false.
// Returns
// - true if a new space was instantiated or an old one could be used.
// - false if the space cannot be created or claimed.
[[nodiscard]] virtual bool Reset(LockboxError* error);
// Hashes, salts, sizes, and stores metadata required for verifying |data|
// in TPM NVRAM for later verification.
//
// Parameters
// - data: blob to store.
// - error: LockboxError populated only on failure
// Returns
// - true if written to disk and NVRAM (if there is a tpm).
// - false if the data could not be persisted.
[[nodiscard]] virtual bool Store(const brillo::Blob& data,
LockboxError* error);
protected:
// constructor for mock testing purpose.
Lockbox() = default;
private:
const hwsec::CryptohomeFrontend* hwsec_;
hwsec::Space space_;
};
// Represents decoded lockbox NVRAM space contents and provides operations to
// encode/decode, as well as setting up and verifying integrity of a specific
// data blob.
class LockboxContents {
public:
enum class VerificationResult {
kValid,
kSizeMismatch,
kHashMismatch,
};
static inline constexpr size_t kFixedPartSize =
sizeof(uint32_t) + sizeof(uint8_t) + SHA256_DIGEST_LENGTH;
static inline constexpr size_t kKeyMaterialSize = 32;
static inline constexpr size_t kNvramSize = kKeyMaterialSize + kFixedPartSize;
// Creates a LockboxContents instance that'll handle encoded lockbox contents
// corresponding to an NVRAM space of size |nvram_size|. Returns nullptr in
// case the passed |nvram_size| isn't supported.
static std::unique_ptr<LockboxContents> New();
size_t key_material_size() const { return key_material_.size(); }
// Serialize to |nvram_data|.
[[nodiscard]] bool Encode(brillo::SecureBlob* nvram_data);
// Deserialize from |nvram_data|.
[[nodiscard]] bool Decode(const brillo::SecureBlob& nvram_data);
// Sets key material, which must be of key_material_size().
[[nodiscard]] bool SetKeyMaterial(const brillo::SecureBlob& key_material);
// Protect |blob|, i.e. compute the digest that will later make Verify() to
// succeed if and only if a copy of |blob| is being passed.
[[nodiscard]] bool Protect(const brillo::Blob& blob);
// Verify |blob| against the lockbox contents.
[[nodiscard]] VerificationResult Verify(const brillo::Blob& blob);
private:
LockboxContents() = default;
uint32_t size_ = 0;
uint8_t flags_ = 0;
brillo::SecureBlob key_material_ = {0};
uint8_t hash_[SHA256_DIGEST_LENGTH] = {0};
};
} // namespace cryptohome
#endif // CRYPTOHOME_LOCKBOX_H_