blob: 36b5f5da4bb5b0a276421aed39f6c8788c76e69f [file] [log] [blame]
// Copyright (c) 2011 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/basictypes.h>
#include <base/scoped_ptr.h>
#include <base/string_util.h>
#include <chromeos/utility.h>
#include "crypto.h"
#include "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, // Indicates tampering or disk corruption.
kErrorIdSizeMismatch, // Indicates tampering or disk corruption.
kErrorIdInsufficientAuthorization, // Indicates 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 crypto implementation.
// Does NOT take ownership of the pointer.
virtual void set_crypto(Crypto* crypto) { crypto_ = crypto; }
virtual Crypto* crypto() { return crypto_; }
// Replaces the tpm implementation.
// Does NOT take ownership of the pointer.
virtual void set_tpm(Tpm* tpm) { tpm_ = tpm; }
virtual Tpm* tpm() { return tpm_; }
// Provide a simple means to access the expected NVRAM contents.
virtual const LockboxContents* contents() const { return contents_.get(); }
// Space reserved for the blob data size.
static const uint32_t kReservedSizeBytes;
static const uint32_t kReservedFlagsBytes;
static const uint32_t kReservedSaltBytes;
static const uint32_t kReservedDigestBytes;
// The sum of the above sizes.
static const uint32_t kReservedNvramBytes;
// 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;
Tpm* tpm_;
uint32_t nvram_index_;
scoped_ptr<Crypto> default_crypto_;
Crypto* crypto_;
scoped_ptr<LockboxContents> contents_;
// Defines the unmarshalled NVRAM contents.
struct LockboxContents {
uint32_t size;
uint8_t flags;
uint8_t hash[SHA256_DIGEST_LENGTH];
bool loaded;
} // namespace cryptohome