| // Copyright (c) 2012 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. |
| // |
| // Lockbox - class for storing tamper-evident data blobs. |
| #ifndef CRYPTOHOME_LOCKBOX_H_ |
| #define CRYPTOHOME_LOCKBOX_H_ |
| |
| #include <memory> |
| |
| #include <openssl/sha.h> |
| |
| #include <base/macros.h> |
| #include <base/strings/string_util.h> |
| #include <brillo/process.h> |
| #include <brillo/secure_blob.h> |
| |
| #include "cryptohome/platform.h" |
| #include "cryptohome/tpm.h" |
| |
| |
| namespace cryptohome { |
| |
| class LockboxContents; |
| |
| // NVRAM structure versions. The enumerator values are chosen to reflect the |
| // corresponding key material sizes for code convenience. |
| enum class NvramVersion : size_t { |
| kVersion1 = 7, |
| kVersion2 = 32, |
| kDefault = kVersion2, |
| }; |
| |
| enum class LockboxError { |
| kNvramSpaceAbsent, |
| kNvramInvalid, |
| kTpmUnavailable, |
| kTpmError, // Transient or unknown TPM error. |
| }; |
| |
| // Enable LockboxError to be used in LOG output. |
| std::ostream& operator<<(std::ostream& out, LockboxError error); |
| |
| // Translates an |NvramVersion| value to a numeric value. |
| int GetNvramVersionNumber(NvramVersion version); |
| |
| // 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(tpm, kNvramSpace); |
| // 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 |
| // - tpm: a required pointer to a TPM object. |
| // - nvram_index: the TPM NVRAM Index to use for this space. |
| // |
| // Lockbox requires a |tpm|. If a NULL |tpm| is supplied, none of the |
| // operations will succeed, but it should not crash or behave unexpectedly. |
| // The |nvram_index| should be chosen carefully. See README.lockbox for info. |
| Lockbox(Tpm* tpm, uint32_t nvram_index); |
| virtual ~Lockbox(); |
| |
| // 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. |
| 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. |
| virtual bool Store(const brillo::Blob& data, LockboxError* error); |
| |
| // Replaces the tpm implementation. |
| // Does NOT take ownership of the pointer. |
| virtual void set_tpm(Tpm* tpm) { tpm_ = tpm; } |
| |
| // Replaces the process spawning implementation. |
| // Does NOT take ownership of the pointer. |
| virtual void set_process(brillo::Process* p) { process_ = p; } |
| |
| // Replaces the Platform class (only used for mount-encrypted). |
| // Does NOT take ownership of the pointer. |
| virtual void set_platform(Platform* p) { platform_ = p; } |
| |
| // Return NVRAM index. |
| virtual uint32_t nvram_index() const { return nvram_index_; } |
| // Return NVRAM version. |
| virtual NvramVersion nvram_version() const { return nvram_version_; } |
| // Replaces the default NVRAM structure version. |
| virtual void set_nvram_version(NvramVersion version) { |
| nvram_version_ = version; |
| } |
| |
| virtual Tpm* tpm() { return tpm_; } |
| |
| // Tells if on this platform we store disk encryption key material in lockbox. |
| // If true, it also requires additional protection for lockbox. |
| // If false, the key material field is just filled with zeroes and not used. |
| // Currently, the key material is stored separately for TPM 2.0. |
| virtual bool IsKeyMaterialInLockbox() const { |
| return tpm_->GetVersion() != Tpm::TpmVersion::TPM_2_0; |
| } |
| |
| protected: |
| // Call out to the mount-encrypted helper to encrypt the key. |
| virtual void FinalizeMountEncrypted(const brillo::SecureBlob &entropy) const; |
| |
| private: |
| Tpm* tpm_; |
| uint32_t nvram_index_; |
| NvramVersion nvram_version_ = NvramVersion::kDefault; |
| std::unique_ptr<brillo::Process> default_process_; |
| brillo::Process* process_; |
| std::unique_ptr<Platform> default_platform_; |
| Platform* platform_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Lockbox); |
| }; |
| |
| // 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 { |
| private: |
| static constexpr size_t kFixedPartSize = |
| sizeof(uint32_t) + sizeof(uint8_t) + SHA256_DIGEST_LENGTH; |
| |
| public: |
| enum class VerificationResult { |
| kValid, |
| kSizeMismatch, |
| kHashMismatch, |
| }; |
| |
| // 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 nvram_size); |
| |
| NvramVersion version() const { |
| return static_cast<NvramVersion>(key_material_.size()); |
| } |
| size_t key_material_size() const { return key_material_.size(); } |
| |
| // Serialize to |nvram_data|. |
| bool Encode(brillo::SecureBlob* nvram_data); |
| |
| // Deserialize from |nvram_data|. |
| bool Decode(const brillo::SecureBlob& nvram_data); |
| |
| // Sets key material, which must be of key_material_size(). |
| 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. |
| bool Protect(const brillo::Blob& blob); |
| |
| // Verify |blob| against the lockbox contents. |
| VerificationResult Verify(const brillo::Blob& blob); |
| |
| static size_t GetNvramSize(NvramVersion version) { |
| return static_cast<size_t>(version) + kFixedPartSize; |
| } |
| |
| 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_ |