blob: 537223f2311fd8f2597074a8b04d221b8ff13d93 [file] [log] [blame]
// 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.
#include <openssl/sha.h>
#include <base/macros.h>
#include <base/memory/scoped_ptr.h>
#include <base/strings/string_util.h>
#include <chromeos/process.h>
#include <chromeos/secure_blob.h>
#include "cryptohome/platform.h"
#include "cryptohome/tpm.h"
namespace cryptohome {
struct LockboxContents;
// 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);
// Lockbox::ErrorId error;
// lockbox->Destroy(&error);
// lockbox->Create(&error);
// lockbox->Store(mah_locked_data, &error);
// Verifying data can be done along these lines:
// Lockbox lockbox(tpm, kNvramSpace);
// lockbox->Load(&error);
// lockbox->Verify(mah_maybe_tampered_with_dat, &error);
// ...
class Lockbox {
typedef enum {
kErrorIdNone = 0,
kErrorIdHashMismatch, // Tampering or disk corruption.
kErrorIdSizeMismatch, // Tampering or disk corruption.
kErrorIdInsufficientAuthorization, // Bad call order or TPM state.
kErrorIdNoNvramSpace, // No space is defined. (legacy install)
kErrorIdNoNvramData, // Empty (unlocked) lockbox
// All errors below indicate any number of system errors.
kErrorIdTpmError, // Transient or unknown TPM error.
} ErrorId;
// 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();
// Creates 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 ErrorId 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 Create(ErrorId* error);
// Destroys all backend state for this Lockbox.
// This call deletes the NVRAM space if defined.
// Parameters
// - error: will contain the ErrorId if false.
// Returns
// - false if TPM Owner authorization is missing or the space cannot be
// destroyed.
// - true if the space is already undefined or has been destroyed.
virtual bool Destroy(ErrorId* error);
// Loads the TPM NVRAM state date into memory
// Parameters
// - error: ErrorId populated only on failure
// Returns
// - true if TPM NVRAM data is properly retrieved.
// - false if the NVRAM data does not exist, is incorrect, or is unlocked.
virtual bool Load(ErrorId* error);
// Verifies the given blob against Load()d data.
// Parameters
// - blob: data blob to verify.
// - error: ErrorId populated only on failure
// Returns
// - true if verified
// - false if the data could not be validated.
virtual bool Verify(const chromeos::Blob& blob, ErrorId* error);
// Hashes, salts, sizes, and stores metadata required for verifying |data|
// in TPM NVRAM for later verification.
// Parameters
// - data: blob to store.
// - error: ErrorId 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 chromeos::Blob& data, ErrorId* 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(chromeos::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 uint32_t nvram_version() const { return nvram_version_; }
// Replaces the default NVRAM structure version.
virtual void set_nvram_version(uint32_t version) { nvram_version_ = version; }
virtual Tpm* tpm() { return tpm_; }
// Provide a simple means to access the expected NVRAM contents.
virtual const LockboxContents* contents() const { return contents_.get(); }
// NVRAM structure versions.
static const uint32_t kNvramVersion1;
static const uint32_t kNvramVersion2;
static const uint32_t kNvramVersionDefault;
// Space reserved for the blob data size.
static const uint32_t kReservedSizeBytes;
static const uint32_t kReservedFlagsBytes;
static const uint32_t kReservedSaltBytesV1;
static const uint32_t kReservedSaltBytesV2;
static const uint32_t kReservedDigestBytes;
// The sum of the above sizes, accounting for possible salts.
static const uint32_t kReservedNvramBytesV1;
static const uint32_t kReservedNvramBytesV2;
// Literals for running mount-encrypted helper.
static const char * const kMountEncrypted;
static const char * const kMountEncryptedFinalize;
// Returns true if we have the authorization needed to create/destroy
// NVRAM spaces.
virtual bool HasAuthorization() const;
// Returns true if the tpm is owned and connected.
virtual bool TpmIsReady() const;
// Serialize the size of data to a Blob.
virtual bool GetSizeBlob(const chromeos::Blob& data,
chromeos::Blob* size_bytes) const;
// Parse a serialized size from the front of |blob|.
virtual bool ParseSizeBlob(const chromeos::Blob& blob, uint32_t* size) const;
// Call out to the mount-encrypted helper to encrypt the key.
virtual void FinalizeMountEncrypted(const chromeos::Blob &entropy) const;
Tpm* tpm_;
uint32_t nvram_index_;
uint32_t nvram_version_;
scoped_ptr<chromeos::Process> default_process_;
chromeos::Process* process_;
scoped_ptr<LockboxContents> contents_;
scoped_ptr<Platform> default_platform_;
Platform* platform_;
// Defines the unmarshalled NVRAM contents.
struct LockboxContents {
uint32_t size;
uint8_t flags;
uint8_t hash[SHA256_DIGEST_LENGTH];
// Remaining variables are used internally and not stored to the NVRAM.
uint32_t salt_size;
bool loaded;
} // namespace cryptohome