Make `cryptohome::Tpm` independent of Cryptohome.

1. Decouple `Tpm` from `TpmInit`.
2. Build TPM into libcrostpm.
3. Move initialization of the TPM from `Tpm` to `TpmInit`.
   House keeping functions such as `LoadTpmStatus`, `StoreTpmStatus`, are
   moved to `TpmInit`.
   Functions related to owner passwords are also moved to `TpmInit`.
4. Move all key loading/saving out of `Tpm` into `TpmInit`.
   `Tpm::Init` is removed. `Tpm` no longer depends on `Platform`.
   `Tpm` instances now MUST be handed handles to context and key in order for
   it to perform any cryptographic operations.
   `TpmInit` can load the key blobs on disk. See
   `TpmInit::LoadCryptohomeKey`.
5. `CreateCryptohomeKey` is replaced with `CreateWrappedRsaKey`. The later
   function uses OpenSSL to generate an RSA key and wraps it with SRK.
6. Add `MockTpmInit`.
7. Make dependency injection clearer in `Init` function. The idiom is:
   construct an object with default constructor then call `Init` and
   pass in necessary dependencies.

BUG=chromium:355634
TEST=unittest
TEST=create an account on the device before applying this CL. download
     some files to its home dir.
TEST=then apply this CL. do it in a way that does not wipe out stateful
     partition.
TEST=do the combo (login, let it idle for a minute or two, reboot) a few
     times. make sure that the existing accounts can still be used and
     downloaded files are still there.
TEST=also make sure that new accounts and guests can login.
TEST=`stop cryptohomed`, then run `cryptohomed --noclose`, make sure
     that there is no apparent problems or warnings related to TPM in the log.

Change-Id: I9a582c9aca8b0cad81520c0a42c68cedf43d5251
Reviewed-on: https://chromium-review.googlesource.com/196911
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Tested-by: Nam Nguyen <namnguyen@chromium.org>
Commit-Queue: Nam Nguyen <namnguyen@chromium.org>
diff --git a/Makefile b/Makefile
index b40009e..080d680 100644
--- a/Makefile
+++ b/Makefile
@@ -47,8 +47,8 @@
 TEST_OBJS := $(filter %_unittest.o cryptohome_testrunner.o %_tests.o mock_%.o, \
                       $(CXX_OBJECTS))
 SHARED_OBJS := $(filter-out cryptohomed.o cryptohome.o cryptohome-path.o \
-                            lockbox-cache-main.o $(ME_OBJS) $(TEST_OBJS), \
-                            $(CXX_OBJECTS))
+                            lockbox-cache-main.o $(ME_OBJS) $(TEST_OBJS) \
+                            tpm.o cryptolib.o, $(CXX_OBJECTS))
 
 # Used to cause an object to depend on all the generated headers. Since the
 # headers are generated, there's no way for common.mk's dependency detection to
@@ -74,6 +74,7 @@
         $(GEN_OBJS), \
         $(call add_gen_hdrs,$(obj))))
 
+all: libcrostpm.a
 all: CXX_BINARY(cryptohomed) CXX_BINARY(cryptohome) CXX_BINARY(cryptohome-path)
 all: CXX_BINARY(lockbox-cache) CC_BINARY(mount-encrypted)
 tests: TEST(CXX_BINARY(cryptohome_testrunner))
@@ -107,17 +108,20 @@
 	mkdir -p $(dir $@)
 	$(DBUS_BINDING_TOOL) --mode=glib-server --prefix=cryptohome $^ > $@
 
-CXX_BINARY(cryptohomed): $(SHARED_OBJS) cryptohomed.o
-CXX_BINARY(cryptohome): $(SHARED_OBJS) cryptohome.o
-CXX_BINARY(cryptohome-path): $(SHARED_OBJS) cryptohome-path.o
+CXX_STATIC_LIBRARY(libcrostpm.pie.a): tpm.o cryptolib.o
+libcrostpm.a: CXX_STATIC_LIBRARY(libcrostpm.pie.a)
+	cp $(OUT)libcrostpm.pie.a $(OUT)libcrostpm.a
+CXX_BINARY(cryptohomed): $(SHARED_OBJS) cryptohomed.o libcrostpm.a
+CXX_BINARY(cryptohome): $(SHARED_OBJS) cryptohome.o libcrostpm.a
+CXX_BINARY(cryptohome-path): $(SHARED_OBJS) cryptohome-path.o libcrostpm.a
 CXX_BINARY(cryptohome_testrunner): LDLIBS += -lgtest -lgmock
-CXX_BINARY(cryptohome_testrunner): $(SHARED_OBJS) $(TEST_OBJS)
+CXX_BINARY(cryptohome_testrunner): $(SHARED_OBJS) $(TEST_OBJS) libcrostpm.a
 CC_BINARY(mount-encrypted): $(ME_OBJS)
-
-CXX_BINARY(lockbox-cache): tpm_status.pb.o cryptolib.o platform.o tpm.o \
-                           lockbox.o lockbox-cache.o lockbox-cache-tpm.o \
-                           lockbox-cache-main.o
+CXX_BINARY(lockbox-cache): tpm_status.pb.o lockbox.o lockbox-cache-tpm.o \
+                           lockbox-cache.o lockbox-cache-main.o platform.o \
+                           libcrostpm.a
 
 clean: CLEAN(*.pb.cc) CLEAN(*.pb.h) CLEAN(cryptohomed) CLEAN(lockbox-cache)
 clean: CLEAN(cryptohome) CLEAN(cryptohome-path) CLEAN(cryptohome_testrunner)
 clean: CLEAN(mount-encrypted) CLEAN($(SHARED_PROTO_FILES))
+clean: CLEAN(libcrostpm.pie.a) libcrostpm.a
diff --git a/attestation.cc b/attestation.cc
index 08b8405..45ab140 100644
--- a/attestation.cc
+++ b/attestation.cc
@@ -26,6 +26,7 @@
 #include "pkcs11_keystore.h"
 #include "platform.h"
 #include "tpm.h"
+#include "tpm_init.h"
 
 using chromeos::SecureBlob;
 using std::string;
@@ -224,12 +225,14 @@
 }
 
 void Attestation::Initialize(Tpm* tpm,
+                             TpmInit* tpm_init,
                              Platform* platform,
                              Crypto* crypto,
                              InstallAttributes* install_attributes) {
   base::AutoLock lock(lock_);
   // Inject dependencies.
   tpm_ = tpm;
+  tpm_init_ = tpm_init;
   platform_ = platform;
   crypto_ = crypto;
   if (install_attributes_ != install_attributes) {
@@ -251,7 +254,7 @@
     FinalizeEndorsementData();
     LOG(INFO) << "Attestation: Valid attestation data exists.";
     // Make sure the owner password is not being held on our account.
-    tpm_->RemoveOwnerDependency(Tpm::kAttestation);
+    tpm_init_->RemoveTpmOwnerDependency(TpmInit::kAttestation);
   }
 }
 
@@ -475,7 +478,7 @@
     LOG(ERROR) << "Attestation: Failed to store db.";
     return;
   }
-  tpm_->RemoveOwnerDependency(Tpm::kAttestation);
+  tpm_init_->RemoveTpmOwnerDependency(TpmInit::kAttestation);
   base::TimeDelta delta = (base::TimeTicks::Now() - start);
   LOG(INFO) << "Attestation: Prepared successfully (" << delta.InMilliseconds()
             << "ms).";
diff --git a/attestation.h b/attestation.h
index 1bb0aca..cd70406 100644
--- a/attestation.h
+++ b/attestation.h
@@ -26,6 +26,7 @@
 class Pkcs11KeyStore;
 class Platform;
 class Tpm;
+class TpmInit;
 
 // This class performs tasks which enable attestation enrollment.  These tasks
 // include creating an AIK and recording all information about the AIK and EK
@@ -46,6 +47,7 @@
 
   // Must be called before any other method.
   virtual void Initialize(Tpm* tpm,
+                          TpmInit* tpm_init,
                           Platform* platform,
                           Crypto* crypto,
                           InstallAttributes* install_attributes);
@@ -379,6 +381,7 @@
   static const char kAlternatePCAKeyIDAttributeName[];
 
   Tpm* tpm_;
+  TpmInit* tpm_init_;
   Platform* platform_;
   Crypto* crypto_;
   // A lock to protect |database_pb_| because PrepareForEnrollment may happen on
@@ -558,6 +561,9 @@
   // Returns true if the TPM is ready.
   bool IsTPMReady();
 
+  // Injects a TpmInit object to be used for RemoveTpmOwnerDependency
+  void set_tpm_init(TpmInit* value) { tpm_init_ = value; }
+
   friend class AttestationTest;
 
   DISALLOW_COPY_AND_ASSIGN(Attestation);
diff --git a/attestation_unittest.cc b/attestation_unittest.cc
index c97ff60..52a7d85 100644
--- a/attestation_unittest.cc
+++ b/attestation_unittest.cc
@@ -21,6 +21,7 @@
 #include "mock_keystore.h"
 #include "mock_platform.h"
 #include "mock_tpm.h"
+#include "mock_tpm_init.h"
 
 using chromeos::SecureBlob;
 using std::string;
@@ -62,7 +63,8 @@
     ON_CALL(tpm_, IsEnabled()).WillByDefault(Return(true));
     ON_CALL(tpm_, IsOwned()).WillByDefault(Return(true));
     ON_CALL(tpm_, IsBeingOwned()).WillByDefault(Return(false));
-    attestation_.Initialize(&tpm_, &platform_, &crypto_, &install_attributes_);
+    attestation_.Initialize(&tpm_, &tpm_init_, &platform_, &crypto_,
+        &install_attributes_);
   }
 
   virtual bool WriteDB(const string& path, const string& db) {
@@ -77,6 +79,7 @@
  protected:
   string serialized_db_;
   NiceMock<MockTpm> tpm_;
+  NiceMock<MockTpmInit> tpm_init_;
   NiceMock<MockPlatform> platform_;
   Crypto crypto_;
   NiceMock<MockKeyStore> key_store_;
@@ -291,8 +294,8 @@
 
 TEST(AttestationTest_, NullTpm) {
   Attestation without_tpm;
-  without_tpm.Initialize(NULL, NULL, new Crypto(NULL),
-                          new InstallAttributes(NULL));
+  without_tpm.Initialize(NULL, NULL, NULL, new Crypto(NULL),
+                         new InstallAttributes(NULL));
   without_tpm.PrepareForEnrollment();
   EXPECT_FALSE(without_tpm.IsPreparedForEnrollment());
   EXPECT_FALSE(without_tpm.Verify());
@@ -606,7 +609,8 @@
               db.credentials().has_endorsement_credential());
 
   // Simulate second login.
-  attestation_.Initialize(&tpm_, &platform_, &crypto_, &install_attributes_);
+  attestation_.Initialize(&tpm_, &tpm_init_, &platform_, &crypto_,
+      &install_attributes_);
   // Expect endorsement data to be no longer available.
   db = GetPersistentDatabase();
   EXPECT_TRUE(db.has_credentials() &&
diff --git a/crypto.cc b/crypto.cc
index 6ece8e9..65b856d 100644
--- a/crypto.cc
+++ b/crypto.cc
@@ -27,6 +27,7 @@
 #include "cryptohome_common.h"
 #include "cryptolib.h"
 #include "platform.h"
+#include "tpm_init.h"
 #include "username_passkey.h"
 
 // Included last because they both have conflicting defines :(
@@ -83,33 +84,30 @@
 Crypto::Crypto(Platform* platform)
     : use_tpm_(false),
       tpm_(NULL),
-      platform_(platform) {
+      platform_(platform),
+      tpm_init_(NULL) {
 }
 
 Crypto::~Crypto() {
 }
 
-bool Crypto::Init() {
-  if (use_tpm_ && tpm_ == NULL) {
-    tpm_ = Tpm::GetSingleton();
-  }
-  if (tpm_) {
-    tpm_->Init(platform_, true);
+bool Crypto::Init(TpmInit* tpm_init) {
+  if (use_tpm_) {
+    CHECK(tpm_init) << "Crypto wanted to use TPM but was not provided a TPM";
+    if (tpm_ == NULL) {
+      tpm_ = tpm_init->get_tpm();
+    }
+    tpm_init_ = tpm_init;
+    tpm_init_->SetupTpm(true);
   }
   return true;
 }
 
-Crypto::CryptoError Crypto::EnsureTpm(bool disconnect_first) const {
+Crypto::CryptoError Crypto::EnsureTpm(bool reload_key) const {
   Crypto::CryptoError result = Crypto::CE_NONE;
-  if (tpm_) {
-    if (disconnect_first) {
-      tpm_->Disconnect();
-    }
-    if (!tpm_->IsConnected()) {
-      Tpm::TpmRetryAction retry_action;
-      if (!tpm_->Connect(&retry_action)) {
-        result = TpmErrorToCrypto(retry_action);
-      }
+  if (tpm_ && tpm_init_) {
+    if (reload_key || !tpm_init_->HasCryptohomeKey()) {
+      tpm_init_->SetupTpm(true);
     }
   }
   return result;
@@ -272,7 +270,9 @@
                              CryptoError* error) const {
   SecureBlob pub_key_hash;
   Tpm::TpmRetryAction retry_action;
-  retry_action = tpm_->GetPublicKeyHash(&pub_key_hash);
+  retry_action = tpm_->GetPublicKeyHash(tpm_init_->GetCryptohomeContext(),
+                                        tpm_init_->GetCryptohomeKey(),
+                                        &pub_key_hash);
   if (retry_action != Tpm::RetryNone) {
     LOG(ERROR) << "Unable to get the cryptohome public key from the TPM.";
     if (error)
@@ -328,7 +328,7 @@
   }
 
   Crypto::CryptoError local_error = EnsureTpm(false);
-  if (!tpm_->IsConnected()) {
+  if (!is_cryptohome_key_loaded()) {
     LOG(ERROR) << "Vault keyset is wrapped by the TPM, but the TPM is "
                << "unavailable";
     if (error)
@@ -350,13 +350,19 @@
     }
   }
 
-  Tpm::TpmRetryAction retry_action;
+  TSS_RESULT result;
   SecureBlob tpm_key(serialized.tpm_key().length());
   serialized.tpm_key().copy(static_cast<char*>(tpm_key.data()),
                             serialized.tpm_key().length(), 0);
   SecureBlob key;
   CryptoLib::PasskeyToAesKey(vault_key, salt, rounds, &key, NULL);
-  if (!tpm_->Decrypt(tpm_key, key, &local_vault_key, &retry_action)) {
+  if (!tpm_->DecryptBlob(tpm_init_->GetCryptohomeContext(),
+                         tpm_init_->GetCryptohomeKey(),
+                         tpm_key,
+                         key,
+                         &local_vault_key,
+                         &result)) {
+    Tpm::TpmRetryAction retry_action = tpm_->HandleError(result);
     LOG(ERROR) << "The TPM failed to unwrap the intermediate key with the "
                << "supplied credentials";
     if (error)
@@ -497,19 +503,24 @@
   if (!use_tpm_)
     return false;
   EnsureTpm(false);
-  if (tpm_ == NULL || !tpm_->IsConnected())
+  if (!is_cryptohome_key_loaded())
     return false;
   SecureBlob local_blob(kDefaultAesKeySize);
   CryptoLib::GetSecureRandom(static_cast<unsigned char*>(local_blob.data()),
                              local_blob.size());
-  Tpm::TpmRetryAction retry_action;
+  TSS_RESULT result;
   SecureBlob tpm_key;
   SecureBlob derived_key;
   CryptoLib::PasskeyToAesKey(key, salt, rounds, &derived_key, NULL);
   // Encrypt the VKK using the TPM and the user's passkey.  The output is an
   // encrypted blob in tpm_key, which is stored in the serialized vault
   // keyset.
-  if (!tpm_->Encrypt(local_blob, derived_key, &tpm_key, &retry_action)) {
+  if (!tpm_->EncryptBlob(tpm_init_->GetCryptohomeContext(),
+                         tpm_init_->GetCryptohomeKey(),
+                         local_blob,
+                         derived_key,
+                         &tpm_key,
+                         &result)) {
     LOG(ERROR) << "Failed to wrap vkk with creds.";
     return false;
   }
@@ -531,7 +542,9 @@
   // detect a TPM clear.  If this fails due to a transient issue, then on next
   // successful login, the vault keyset will be re-saved anyway.
   SecureBlob pub_key_hash;
-  if (tpm_->GetPublicKeyHash(&pub_key_hash) == Tpm::RetryNone)
+  if (tpm_->GetPublicKeyHash(tpm_init_->GetCryptohomeContext(),
+                             tpm_init_->GetCryptohomeKey(),
+                             &pub_key_hash) == Tpm::RetryNone)
     serialized->set_tpm_public_key_hash(pub_key_hash.const_data(),
                                         pub_key_hash.size());
 
@@ -749,4 +762,11 @@
   return true;
 }
 
+bool Crypto::is_cryptohome_key_loaded() const {
+  if (tpm_ == NULL || tpm_init_ == NULL) {
+    return false;
+  }
+  return tpm_init_->HasCryptohomeKey();
+}
+
 }  // namespace cryptohome
diff --git a/crypto.h b/crypto.h
index 6ec0fe9..e758355 100644
--- a/crypto.h
+++ b/crypto.h
@@ -15,6 +15,7 @@
 #include <chromeos/secure_blob.h>
 
 #include "tpm.h"
+#include "tpm_init.h"
 #include "vault_keyset.h"
 #include "vault_keyset.pb.h"
 
@@ -41,7 +42,7 @@
   virtual ~Crypto();
 
   // Initializes Crypto
-  bool Init();
+  bool Init(TpmInit* tpm_init);
 
   // Decrypts an encrypted vault keyset.  The vault keyset should be the output
   // of EncryptVaultKeyset().
@@ -118,7 +119,7 @@
                                 chromeos::SecureBlob* passkey);
 
   // Ensures that the TPM is connected
-  CryptoError EnsureTpm(bool disconnect_first) const;
+  CryptoError EnsureTpm(bool reload_key) const;
 
   // Seals arbitrary-length data to the TPM's PCR0.
   // Parameters
@@ -185,13 +186,8 @@
     return tpm_;
   }
 
-  // Checks if the TPM is connected
-  bool is_tpm_connected() {
-    if (tpm_ == NULL) {
-      return false;
-    }
-    return tpm_->IsConnected();
-  }
+  // Checks if the cryptohome key is loaded in TPM
+  bool is_cryptohome_key_loaded() const;
 
   // Sets the Platform implementation
   // Does NOT take ownership of the pointer.
@@ -249,6 +245,9 @@
   // Platform abstraction
   Platform* platform_;
 
+  // The TpmInit object used to reload Cryptohome key
+  TpmInit* tpm_init_;
+
   DISALLOW_COPY_AND_ASSIGN(Crypto);
 };
 
diff --git a/crypto_unittest.cc b/crypto_unittest.cc
index 29f4459..253093a 100644
--- a/crypto_unittest.cc
+++ b/crypto_unittest.cc
@@ -22,12 +22,14 @@
 #include "cryptolib.h"
 #include "mock_platform.h"
 #include "mock_tpm.h"
+#include "mock_tpm_init.h"
 
 using base::FilePath;
 using chromeos::Blob;
 using chromeos::SecureBlob;
 using std::string;
 using ::testing::_;
+using ::testing::AtLeast;
 using ::testing::DoAll;
 using ::testing::Return;
 using ::testing::SaveArg;
@@ -310,18 +312,20 @@
   MockPlatform platform;
   Crypto crypto(&platform);
   NiceMock<MockTpm> tpm;
+  NiceMock<MockTpmInit> tpm_init;
 
   crypto.set_tpm(&tpm);
   crypto.set_use_tpm(true);
 
-  EXPECT_CALL(tpm, Init(_, _))
-      .WillOnce(Return(true));
-  EXPECT_CALL(tpm, Encrypt(_, _, _, _));
-  EXPECT_CALL(tpm, Decrypt(_, _, _, _));
-  EXPECT_CALL(tpm, IsConnected())
+  EXPECT_CALL(tpm, EncryptBlob(_, _, _, _, _, _));
+  EXPECT_CALL(tpm, DecryptBlob(_, _, _, _, _, _));
+  EXPECT_CALL(tpm_init, HasCryptohomeKey())
+      .WillOnce(Return(false))
       .WillRepeatedly(Return(true));
+  EXPECT_CALL(tpm_init, SetupTpm(true))
+      .Times(AtLeast(2));  // One by crypto.Init(), one by crypto.EnsureTpm()
 
-  crypto.Init();
+  crypto.Init(&tpm_init);
 
   VaultKeyset vault_keyset;
   vault_keyset.Initialize(&platform_, &crypto);
@@ -364,7 +368,7 @@
   MockPlatform platform;
   Crypto crypto(&platform);
 
-  crypto.Init();
+  crypto.Init(NULL);
 
   VaultKeyset vault_keyset;
   vault_keyset.Initialize(&platform, &crypto);
@@ -408,15 +412,15 @@
   MockPlatform platform;
   Crypto crypto(&platform);
   NiceMock<MockTpm> tpm;
+  NiceMock<MockTpmInit> tpm_init;
 
   crypto.set_tpm(&tpm);
   crypto.set_use_tpm(true);
 
-  EXPECT_CALL(tpm, Init(_, _)).WillOnce(Return(true));
-  EXPECT_CALL(tpm, Encrypt(_, _, _, _));
-  EXPECT_CALL(tpm, Decrypt(_, _, _, _));
+  EXPECT_CALL(tpm, EncryptBlob(_, _, _, _, _, _));
+  EXPECT_CALL(tpm, DecryptBlob(_, _, _, _, _, _));
 
-  crypto.Init();
+  crypto.Init(&tpm_init);
 
   VaultKeyset vault_keyset;
   vault_keyset.Initialize(&platform_, &crypto);
@@ -517,11 +521,10 @@
   Crypto crypto(&platform);
 
   NiceMock<MockTpm> tpm;
+  NiceMock<MockTpmInit> tpm_init;
   crypto.set_tpm(&tpm);
   crypto.set_use_tpm(true);
-  EXPECT_CALL(tpm, Init(_, _))
-      .WillOnce(Return(true));
-  crypto.Init();
+  crypto.Init(&tpm_init);
 
   string data = "iamsomestufftoencrypt";
   SecureBlob data_blob(data.data(), data.size());
@@ -561,11 +564,10 @@
   Crypto crypto(&platform);
 
   NiceMock<MockTpm> tpm;
+  NiceMock<MockTpmInit> tpm_init;
   crypto.set_tpm(&tpm);
   crypto.set_use_tpm(true);
-  EXPECT_CALL(tpm, Init(_, _))
-      .WillOnce(Return(true));
-  crypto.Init();
+  crypto.Init(&tpm_init);
 
   string data = "iamsomestufftoencrypt";
   SecureBlob data_blob(data.data(), data.size());
diff --git a/homedirs.cc b/homedirs.cc
index dda7539..c59f7e4 100644
--- a/homedirs.cc
+++ b/homedirs.cc
@@ -39,8 +39,7 @@
       enterprise_owned_(false),
       default_policy_provider_(new policy::PolicyProvider()),
       policy_provider_(default_policy_provider_.get()),
-      default_crypto_(new Crypto(platform_)),
-      crypto_(default_crypto_.get()),
+      crypto_(NULL),
       default_mount_factory_(new MountFactory()),
       mount_factory_(default_mount_factory_.get()),
       default_vault_keyset_factory_(new VaultKeysetFactory()),
@@ -48,7 +47,10 @@
 
 HomeDirs::~HomeDirs() { }
 
-bool HomeDirs::Init() {
+bool HomeDirs::Init(Platform* platform, Crypto* crypto) {
+  platform_ = platform;
+  crypto_ = crypto;
+
   LoadDevicePolicy();
   if (!platform_->DirectoryExists(shadow_root_))
     platform_->CreateDirectory(shadow_root_);
@@ -812,9 +814,7 @@
   newcreds.GetPasskey(&newkey);
   UsernamePasskey oldcreds(newcreds.username().c_str(), oldkey);
   scoped_refptr<Mount> mount = mount_factory_->New();
-  mount->set_platform(platform_);
-  mount->set_crypto(crypto_);
-  mount->Init();
+  mount->Init(platform_, crypto_);
   std::string obfuscated = newcreds.GetObfuscatedUsername(system_salt_);
   if (!mount->MountCryptohome(oldcreds, Mount::MountArgs(), NULL)) {
     LOG(ERROR) << "Migrate: Mount failed";
diff --git a/homedirs.h b/homedirs.h
index 0be9e93..1fae11a 100644
--- a/homedirs.h
+++ b/homedirs.h
@@ -40,7 +40,7 @@
   virtual ~HomeDirs();
 
   // Initializes this HomeDirs object. Returns true for success.
-  virtual bool Init();
+  virtual bool Init(Platform* platform, Crypto* crypto);
 
   // Frees disk space for unused cryptohomes. If less than kMinFreeSpace is
   // available, frees space until kEnoughFreeSpace is available. Returns true if
@@ -229,7 +229,6 @@
   bool enterprise_owned_;
   scoped_ptr<policy::PolicyProvider> default_policy_provider_;
   policy::PolicyProvider* policy_provider_;
-  scoped_ptr<Crypto> default_crypto_;
   Crypto* crypto_;
   scoped_ptr<MountFactory> default_mount_factory_;
   MountFactory* mount_factory_;
diff --git a/homedirs_unittest.cc b/homedirs_unittest.cc
index d4b7dfe..7f5dff1 100644
--- a/homedirs_unittest.cc
+++ b/homedirs_unittest.cc
@@ -15,6 +15,7 @@
 
 #include "cryptolib.h"
 #include "make_tests.h"
+#include "mock_crypto.h"
 #include "mock_platform.h"
 #include "mock_tpm.h"
 #include "mock_user_oldest_activity_timestamp_cache.h"
@@ -104,8 +105,7 @@
     test_helper_.SetUpSystemSalt();
     // TODO(wad) Only generate the user data we need. This is time consuming.
     test_helper_.InitTestData(kTestRoot, kDefaultUsers, kDefaultUserCount);
-    homedirs_.set_platform(&platform_);
-    homedirs_.crypto()->set_platform(&platform_);
+    crypto_.set_platform(&platform_);
     homedirs_.set_shadow_root(kTestRoot);
     test_helper_.InjectSystemSalt(&platform_,
                                   StringPrintf("%s/salt", kTestRoot));
@@ -114,7 +114,7 @@
     // Mount() normally sets this.
     homedirs_.set_timestamp_cache(&timestamp_cache_);
 
-    homedirs_.Init();
+    homedirs_.Init(&platform_, &crypto_);
     FilePath fp = FilePath(kTestRoot);
     for (unsigned int i = 0; i < arraysize(kHomedirs); i++) {
       const struct homedir *hd = &kHomedirs[i];
@@ -150,6 +150,7 @@
 
  protected:
   HomeDirs homedirs_;
+  NiceMock<MockCrypto> crypto_;
   NiceMock<MockPlatform> platform_;
   std::vector<std::string> homedir_paths_;
   MakeTests test_helper_;
diff --git a/install_attributes.cc b/install_attributes.cc
index 10e5d3b..041bcd6 100644
--- a/install_attributes.cc
+++ b/install_attributes.cc
@@ -11,6 +11,7 @@
 
 #include "lockbox.h"
 #include "install_attributes.pb.h"
+#include "tpm_init.h"
 
 namespace cryptohome {
 
@@ -78,7 +79,7 @@
   lockbox_->set_tpm(tpm);
 }
 
-bool InstallAttributes::Init() {
+bool InstallAttributes::Init(TpmInit* tpm_init) {
   Lockbox::ErrorId error_id;
 
   // Insure that if Init() was called and it failed, we can retry cleanly.
@@ -100,7 +101,7 @@
     }
 
     set_is_initialized(true);
-    lockbox_->tpm()->RemoveOwnerDependency(Tpm::kInstallAttributes);
+    tpm_init->RemoveTpmOwnerDependency(TpmInit::kInstallAttributes);
     return true;
   }
 
diff --git a/install_attributes.h b/install_attributes.h
index e24e102..85ac3a9 100644
--- a/install_attributes.h
+++ b/install_attributes.h
@@ -18,6 +18,7 @@
 #include "lockbox.h"
 #include "platform.h"
 #include "tpm.h"
+#include "tpm_init.h"
 
 namespace cryptohome {
 
@@ -38,7 +39,7 @@
 
   // Creates an instance of install attributes that will use the |tpm|. If |tpm|
   // is NULL, InstallAttributes will proceed insecurely (unless it is set with
-  // set_tpm at a later time).
+  // SetTpm at a later time).
   explicit InstallAttributes(Tpm* tpm);
   virtual ~InstallAttributes();
 
@@ -52,8 +53,9 @@
   virtual void SetTpm(Tpm* tpm);
 
   // Prepares the class for use including instantiating a new environment
-  // if needed.
-  virtual bool Init();
+  // if needed. If initialization completes, |tpm_init| will be used to remove
+  // this instance's dependency on the TPM ownership.
+  virtual bool Init(TpmInit* tpm_init);
 
   // Determines if the instance can provide consistent responses to Get*(),
   // Set(), Finalize(), and Count().  Repeated calls to Init() may change this.
diff --git a/install_attributes_unittest.cc b/install_attributes_unittest.cc
index 8043c34..be48ec8 100644
--- a/install_attributes_unittest.cc
+++ b/install_attributes_unittest.cc
@@ -17,6 +17,7 @@
 #include "mock_lockbox.h"
 #include "mock_platform.h"
 #include "mock_tpm.h"
+#include "mock_tpm_init.h"
 
 namespace cryptohome {
 using std::string;
@@ -78,10 +79,12 @@
     if (install_attrs->is_secure()) {
       EXPECT_CALL(lockbox_, Create(_))
         .WillOnce(Return(true));
-      EXPECT_CALL(tpm_, RemoveOwnerDependency(Tpm::kInstallAttributes))
+      EXPECT_CALL(tpm_init_,
+                  RemoveTpmOwnerDependency(
+                      TpmInit::kInstallAttributes))
         .Times(1);
     }
-    EXPECT_TRUE(install_attrs->Init());
+    EXPECT_TRUE(install_attrs->Init(&tpm_init_));
 
     chromeos::Blob data;
     data.assign(kTestData, kTestData + strlen(kTestData));
@@ -127,6 +130,7 @@
   InstallAttributes install_attrs_;
   NiceMock<MockPlatform> platform_;
   NiceMock<MockTpm> tpm_;
+  NiceMock<MockTpmInit> tpm_init_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InstallAttributesTest);
@@ -152,8 +156,7 @@
   EXPECT_CALL(platform_, ReadFile(_, _))
     .Times(1)
     .WillOnce(Return(false));
-
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_TRUE(install_attrs_.is_first_install());
 }
 
@@ -167,7 +170,7 @@
     .WillRepeatedly(Return(&tpm_));
   EXPECT_CALL(lockbox_, Create(_))
     .WillOnce(Return(true));
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
 
   chromeos::Blob data;
   data.assign(kTestData, kTestData + strlen(kTestData));
@@ -204,7 +207,7 @@
   EXPECT_CALL(lockbox_, Verify(_, _))
     .Times(1)
     .WillOnce(Return(true));
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_FALSE(install_attrs_.is_invalid());
   EXPECT_TRUE(install_attrs_.is_initialized());
@@ -231,7 +234,7 @@
     .Times(1)
     .WillOnce(DoAll(SetArgumentPointee<1>(serialized_data), Return(true)));
 
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_FALSE(install_attrs_.is_invalid());
   EXPECT_TRUE(install_attrs_.is_initialized());
@@ -263,7 +266,7 @@
   EXPECT_CALL(lockbox_, Load(_))
     .Times(1)
     .WillOnce(DoAll(SetArgumentPointee<0>(error_id), Return(false)));
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_TRUE(install_attrs_.is_first_install());
   EXPECT_FALSE(install_attrs_.is_invalid());
   EXPECT_TRUE(install_attrs_.is_initialized());
@@ -294,7 +297,7 @@
   EXPECT_CALL(lockbox_, Create(_))
     .Times(1)
     .WillOnce(Return(true));
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_TRUE(install_attrs_.is_first_install());
   EXPECT_FALSE(install_attrs_.is_invalid());
   EXPECT_TRUE(install_attrs_.is_initialized());
@@ -313,7 +316,7 @@
   EXPECT_CALL(lockbox_, Load(_))
     .Times(1)
     .WillOnce(DoAll(SetArgumentPointee<0>(error_id), Return(false)));
-  EXPECT_FALSE(install_attrs_.Init());
+  EXPECT_FALSE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_TRUE(install_attrs_.is_invalid());
   EXPECT_FALSE(install_attrs_.is_initialized());
@@ -334,7 +337,7 @@
   EXPECT_CALL(platform_, ReadFile(_, _))
     .Times(1)
     .WillOnce(Return(false));
-  EXPECT_FALSE(install_attrs_.Init());
+  EXPECT_FALSE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_TRUE(install_attrs_.is_invalid());
   EXPECT_FALSE(install_attrs_.is_initialized());
@@ -362,7 +365,7 @@
     .Times(1)
     .WillOnce(DoAll(SetArgumentPointee<1>(error_id), Return(false)));
 
-  EXPECT_FALSE(install_attrs_.Init());
+  EXPECT_FALSE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_TRUE(install_attrs_.is_invalid());
   EXPECT_FALSE(install_attrs_.is_initialized());
@@ -385,7 +388,7 @@
   EXPECT_CALL(lockbox_, Create(_))
     .Times(1)
     .WillOnce(DoAll(SetArgumentPointee<0>(create_error_id), Return(false)));
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_FALSE(install_attrs_.is_invalid());
   EXPECT_TRUE(install_attrs_.is_initialized());
@@ -410,7 +413,7 @@
   EXPECT_CALL(lockbox_, Create(_))
     .Times(1)
     .WillOnce(DoAll(SetArgumentPointee<0>(create_error_id), Return(false)));
-  EXPECT_TRUE(install_attrs_.Init());
+  EXPECT_TRUE(install_attrs_.Init(&tpm_init_));
   EXPECT_FALSE(install_attrs_.is_first_install());
   EXPECT_FALSE(install_attrs_.is_invalid());
   EXPECT_TRUE(install_attrs_.is_initialized());
diff --git a/make_tests.cc b/make_tests.cc
index 2df4ad0..895455e 100644
--- a/make_tests.cc
+++ b/make_tests.cc
@@ -24,6 +24,7 @@
 #include <gtest/gtest.h>
 
 #include "crypto.h"
+#include "mock_crypto.h"
 #include "mock_platform.h"
 #include "mock_tpm.h"
 #include "mount.h"
@@ -178,13 +179,10 @@
   memcpy(&salt.at(0), system_salt->c_str(), system_salt->size());
   NiceMock<MockTpm> tpm;
   NiceMock<MockPlatform> platform;
-  //MockPlatform platform;
+  NiceMock<MockCrypto> crypto;
+  crypto.set_platform(&platform);
+
   scoped_refptr<Mount> mount = new cryptohome::Mount();
-  mount->set_platform(&platform);
-  mount->crypto()->set_tpm(&tpm);
-  mount->crypto()->set_platform(&platform);
-  mount->homedirs()->set_platform(&platform);
-  mount->homedirs()->crypto()->set_platform(&platform);
   mount->set_shadow_root(shadow_root);
   mount->set_skel_source(skel_dir);
   mount->set_use_tpm(false);
@@ -203,7 +201,7 @@
     .WillRepeatedly(DoAll(SetArgumentPointee<1>(salt), Return(true)));
   EXPECT_CALL(platform, DirectoryExists(shadow_root))
     .WillRepeatedly(Return(true));
-   mount->Init();
+  mount->Init(&platform, &crypto);
 
   cryptohome::Crypto::PasswordToPasskey(password,
                                         salt,
diff --git a/mock_attestation.h b/mock_attestation.h
index d4a9105..1387d30 100644
--- a/mock_attestation.h
+++ b/mock_attestation.h
@@ -21,7 +21,11 @@
   MockAttestation(): Attestation() { }
   virtual ~MockAttestation() {}
 
-  MOCK_METHOD4(Initialize, void(Tpm*, Platform*, Crypto*, InstallAttributes*));
+  MOCK_METHOD5(Initialize, void(Tpm*,
+                                TpmInit*,
+                                Platform*,
+                                Crypto*,
+                                InstallAttributes*));
   MOCK_METHOD0(IsPreparedForEnrollment, bool());
   MOCK_METHOD0(IsEnrolled, bool());
   MOCK_METHOD0(PrepareForEnrollment, void());
diff --git a/mock_homedirs.cc b/mock_homedirs.cc
index 1038cd0..b84f3e6 100644
--- a/mock_homedirs.cc
+++ b/mock_homedirs.cc
@@ -4,12 +4,13 @@
 
 #include "mock_homedirs.h"
 
+using testing::_;
 using testing::Return;
 
 namespace cryptohome {
 
 MockHomeDirs::MockHomeDirs() {
-  ON_CALL(*this, Init()).WillByDefault(Return(true));
+  ON_CALL(*this, Init(_, _)).WillByDefault(Return(true));
 }
 MockHomeDirs::~MockHomeDirs() {}
 
diff --git a/mock_homedirs.h b/mock_homedirs.h
index 58af032..36f6501 100644
--- a/mock_homedirs.h
+++ b/mock_homedirs.h
@@ -20,7 +20,7 @@
   MockHomeDirs();
   virtual ~MockHomeDirs();
 
-  MOCK_METHOD0(Init, bool());
+  MOCK_METHOD2(Init, bool(Platform*, Crypto*));
   MOCK_METHOD0(FreeDiskSpace, bool());
   MOCK_METHOD1(AreCredentialsValid, bool(const Credentials&));
   MOCK_METHOD2(GetValidKeyset, bool(const Credentials&, VaultKeyset*));
diff --git a/mock_install_attributes.h b/mock_install_attributes.h
index cde6803..d1ae6de 100644
--- a/mock_install_attributes.h
+++ b/mock_install_attributes.h
@@ -14,6 +14,7 @@
 
 #include "lockbox.h"
 #include "tpm.h"
+#include "tpm_init.h"
 
 namespace cryptohome {
 
@@ -26,7 +27,7 @@
 
   MOCK_METHOD1(SetTpm, void(Tpm*));
 
-  MOCK_METHOD0(Init, bool());
+  MOCK_METHOD1(Init, bool(TpmInit*));
 
   MOCK_CONST_METHOD0(IsReady, bool());
 
diff --git a/mock_mount.h b/mock_mount.h
index 295f625..b8be438 100644
--- a/mock_mount.h
+++ b/mock_mount.h
@@ -16,7 +16,7 @@
  public:
   MockMount();
   ~MockMount();
-  MOCK_METHOD0(Init, bool());
+  MOCK_METHOD2(Init, bool(Platform*, Crypto*));
   MOCK_METHOD1(AreSameUser, bool(const Credentials&));
   MOCK_METHOD1(AreValid, bool(const Credentials&));
   MOCK_METHOD3(MountCryptohome, bool(const Credentials&,
diff --git a/mock_tpm.cc b/mock_tpm.cc
index 8d9ea2d..10857fa 100644
--- a/mock_tpm.cc
+++ b/mock_tpm.cc
@@ -12,20 +12,16 @@
 namespace cryptohome {
 
 MockTpm::MockTpm() {
-  ON_CALL(*this, Encrypt(_, _, _, _))
+  ON_CALL(*this, EncryptBlob(_, _, _, _, _, _))
       .WillByDefault(Invoke(this, &MockTpm::Xor));
-  ON_CALL(*this, Decrypt(_, _, _, _))
+  ON_CALL(*this, DecryptBlob(_, _, _, _, _, _))
       .WillByDefault(Invoke(this, &MockTpm::Xor));
-  ON_CALL(*this, IsConnected())
-      .WillByDefault(Return(true));
   ON_CALL(*this, Connect(_))
       .WillByDefault(Return(true));
   ON_CALL(*this, GetPublicKey(_, _))
       .WillByDefault(Invoke(this, &MockTpm::GetBlankPublicKey));
-  ON_CALL(*this, GetPublicKeyHash(_))
+  ON_CALL(*this, GetPublicKeyHash(_, _, _))
       .WillByDefault(Return(Tpm::Fatal));
-  ON_CALL(*this, Init(_, _))
-      .WillByDefault(Return(true));
   ON_CALL(*this, GetEndorsementPublicKey(_))
       .WillByDefault(Return(true));
   ON_CALL(*this, GetEndorsementCredential(_))
diff --git a/mock_tpm.h b/mock_tpm.h
index 25d14dc..f0e0f6a 100644
--- a/mock_tpm.h
+++ b/mock_tpm.h
@@ -24,22 +24,22 @@
  public:
   MockTpm();
   ~MockTpm();
-  MOCK_METHOD2(Init, bool(Platform*, bool));
-  MOCK_METHOD0(IsConnected, bool());
   MOCK_CONST_METHOD0(IsOwned, bool());
   MOCK_CONST_METHOD0(IsBeingOwned, bool());
   MOCK_METHOD1(Connect, bool(TpmRetryAction*));  // NOLINT
-  MOCK_METHOD0(Disconnect, void());
-  MOCK_METHOD4(Encrypt, bool(const chromeos::SecureBlob&,
-                             const chromeos::SecureBlob&,
-                                   chromeos::SecureBlob*, TpmRetryAction*));
-  MOCK_METHOD4(Decrypt, bool(const chromeos::SecureBlob&,
-                             const chromeos::SecureBlob&,
-                                   chromeos::SecureBlob*, TpmRetryAction*));
+  MOCK_METHOD6(EncryptBlob, bool(TSS_HCONTEXT, TSS_HKEY,
+                                 const chromeos::SecureBlob&,
+                                 const chromeos::SecureBlob&,
+                                 chromeos::SecureBlob*, TSS_RESULT*));
+  MOCK_METHOD6(DecryptBlob, bool(TSS_HCONTEXT, TSS_HKEY,
+                                 const chromeos::SecureBlob&,
+                                 const chromeos::SecureBlob&,
+                                 chromeos::SecureBlob*, TSS_RESULT*));
   MOCK_METHOD2(GetPublicKey, bool(chromeos::SecureBlob*, TpmRetryAction*));
-  MOCK_METHOD1(GetPublicKeyHash, Tpm::TpmRetryAction(chromeos::SecureBlob*));
+  MOCK_METHOD3(GetPublicKeyHash, Tpm::TpmRetryAction(TSS_HCONTEXT,
+                                                     TSS_HKEY,
+                                                     chromeos::SecureBlob*));
   MOCK_METHOD1(GetOwnerPassword, bool(chromeos::Blob*));
-  MOCK_METHOD1(RemoveOwnerDependency, void(Tpm::TpmOwnerDependency));
   MOCK_CONST_METHOD0(IsEnabled, bool());
   MOCK_METHOD2(GetRandomData, bool(size_t, chromeos::Blob*));
   MOCK_METHOD2(DefineLockOnceNvram, bool(uint32_t, size_t));
@@ -96,10 +96,12 @@
   MOCK_METHOD2(ExtendPCR, bool(int, const chromeos::SecureBlob&));
 
  private:
-  bool Xor(const chromeos::SecureBlob& plaintext,
+  bool Xor(TSS_HCONTEXT _context,
+           TSS_HKEY _key,
+           const chromeos::SecureBlob& plaintext,
            const chromeos::SecureBlob& key,
            chromeos::SecureBlob* ciphertext,
-           TpmRetryAction* retry_action) {
+           TSS_RESULT* result) {
     chromeos::SecureBlob local_data_out(plaintext.size());
     for (unsigned int i = 0; i < local_data_out.size(); i++) {
       local_data_out[i] = plaintext[i] ^ 0x1e;
diff --git a/mock_tpm_init.cc b/mock_tpm_init.cc
new file mode 100644
index 0000000..aed9c31
--- /dev/null
+++ b/mock_tpm_init.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 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 "mock_tpm_init.h"
+
+using testing::_;
+using testing::Return;
+
+namespace cryptohome {
+
+MockTpmInit::MockTpmInit() : TpmInit(NULL, NULL) {
+  ON_CALL(*this, SetupTpm(_))
+      .WillByDefault(Return(true));
+  ON_CALL(*this, HasCryptohomeKey())
+      .WillByDefault(Return(true));
+}
+
+MockTpmInit::~MockTpmInit() {}
+
+}  // namespace cryptohome
diff --git a/mock_tpm_init.h b/mock_tpm_init.h
new file mode 100644
index 0000000..c6535a9
--- /dev/null
+++ b/mock_tpm_init.h
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+#ifndef CRYPTOHOME_MOCK_TPM_INIT_H_
+#define CRYPTOHOME_MOCK_TPM_INIT_H_
+
+#include "tpm_init.h"
+
+#include <gmock/gmock.h>
+
+namespace cryptohome {
+
+class MockTpmInit : public TpmInit {
+ public:
+  MockTpmInit();
+  ~MockTpmInit();
+
+  MOCK_METHOD1(SetupTpm, bool(bool));
+  MOCK_METHOD1(RemoveTpmOwnerDependency, void(TpmOwnerDependency));
+  MOCK_METHOD0(HasCryptohomeKey, bool());
+};
+
+}  // namespace cryptohome
+
+#endif  // CRYPTOHOME_MOCK_TPM_INIT_H_
diff --git a/mount.cc b/mount.cc
index de3f0ed..0dfe63f 100644
--- a/mount.cc
+++ b/mount.cc
@@ -108,8 +108,7 @@
       system_salt_(),
       default_platform_(new Platform()),
       platform_(default_platform_.get()),
-      default_crypto_(new Crypto(platform_)),
-      crypto_(default_crypto_.get()),
+      crypto_(NULL),
       default_homedirs_(new HomeDirs()),
       homedirs_(default_homedirs_.get()),
       use_tpm_(true),
@@ -131,7 +130,10 @@
     UnmountCryptohome();
 }
 
-bool Mount::Init() {
+bool Mount::Init(Platform* platform, Crypto* crypto) {
+  platform_ = platform;
+  crypto_ = crypto;
+
   bool result = true;
 
   homedirs_->set_platform(platform_);
@@ -142,8 +144,7 @@
   // Make sure both we and |homedirs_| have a proper device policy object.
   EnsureDevicePolicyLoaded(false);
   homedirs_->set_policy_provider(policy_provider_.get());
-  homedirs_->set_crypto(crypto_);
-  if (!homedirs_->Init())
+  if (!homedirs_->Init(platform, crypto))
     result = false;
 
   // Get the user id and group id of the default user
@@ -164,19 +165,12 @@
     result = false;
   }
 
-  crypto_->set_use_tpm(use_tpm_);
-
   int original_mask = platform_->SetMask(kDefaultUmask);
   // Create the shadow root if it doesn't exist
   if (!platform_->DirectoryExists(shadow_root_)) {
     platform_->CreateDirectory(shadow_root_);
   }
 
-  if (!crypto_->Init()) {
-    LOG(ERROR) << "Failed to initialize a Crypto instance";
-    result = false;
-  }
-
   // One-time load of the global system salt (used in generating username
   // hashes)
   FilePath system_salt_file(StringPrintf("%s/salt", shadow_root_.c_str()));
@@ -1111,7 +1105,7 @@
   bool scrypt_wrapped =
       (crypt_flags & SerializedVaultKeyset::SCRYPT_WRAPPED) != 0;
   bool should_tpm = (crypto_->has_tpm() && use_tpm_ &&
-                     crypto_->is_tpm_connected());
+                     crypto_->is_cryptohome_key_loaded());
   bool should_scrypt = true;
   do {
     // If the keyset was TPM-wrapped, but there was no public key hash,
diff --git a/mount.h b/mount.h
index ee7ae0a..38cea81 100644
--- a/mount.h
+++ b/mount.h
@@ -86,7 +86,7 @@
   virtual ~Mount();
 
   // Gets the uid/gid of the default user and loads the system salt
-  virtual bool Init();
+  virtual bool Init(Platform* platform, Crypto* crypto);
 
   // Attempts to mount the cryptohome for the given credentials
   //
@@ -723,7 +723,6 @@
   Platform *platform_;
 
   // The crypto implementation
-  scoped_ptr<Crypto> default_crypto_;
   Crypto *crypto_;
 
   // TODO(wad,ellyjones) Require HomeDirs at Init().
diff --git a/mount_unittest.cc b/mount_unittest.cc
index 65fc6f4..0d8b3ac 100644
--- a/mount_unittest.cc
+++ b/mount_unittest.cc
@@ -31,9 +31,11 @@
 #include "homedirs.h"
 #include "make_tests.h"
 #include "mock_chaps_client_factory.h"
+#include "mock_crypto.h"
 #include "mock_homedirs.h"
 #include "mock_platform.h"
 #include "mock_tpm.h"
+#include "mock_tpm_init.h"
 #include "mock_user_session.h"
 #include "username_passkey.h"
 #include "vault_keyset.h"
@@ -78,14 +80,16 @@
 }
 
 // Straight pass through.
-bool TpmPassthroughEncrypt(const chromeos::SecureBlob &plaintext, Unused,
+bool TpmPassthroughEncrypt(TSS_HCONTEXT _context, TSS_HKEY _key,
+                           const chromeos::SecureBlob &plaintext, Unused,
                            chromeos::SecureBlob *ciphertext, Unused) {
   ciphertext->resize(plaintext.size());
   memcpy(ciphertext->data(), plaintext.const_data(), plaintext.size());
   return true;
 }
 
-bool TpmPassthroughDecrypt(const chromeos::SecureBlob &ciphertext, Unused,
+bool TpmPassthroughDecrypt(TSS_HCONTEXT _context, TSS_HKEY _key,
+                           const chromeos::SecureBlob &ciphertext, Unused,
                            chromeos::SecureBlob *plaintext, Unused) {
   plaintext->resize(ciphertext.size());
   memcpy(plaintext->data(), ciphertext.const_data(), ciphertext.size());
@@ -108,16 +112,17 @@
     shared_gid_ = 1001;
     chaps_uid_ = 223;
 
+    crypto_.set_tpm(&tpm_);
+    crypto_.set_platform(&platform_);
+    crypto_.set_use_tpm(false);
+
     mount_ = new Mount();
-    mount_->set_platform(&platform_);
     mount_->set_homedirs(&homedirs_);
     mount_->set_use_tpm(false);
     mount_->set_shadow_root(kImageDir);
     mount_->set_skel_source(kSkelDir);
-    mount_->crypto()->set_platform(&platform_);
-    mount_->crypto()->set_tpm(&tpm_);
     mount_->set_chaps_client_factory(&chaps_client_factory_);
-    homedirs_.set_crypto(mount_->crypto());
+    homedirs_.set_crypto(&crypto_);
     homedirs_.set_platform(&platform_);
     homedirs_.set_shadow_root(kImageDir);
     set_policy(false, "", false);
@@ -145,7 +150,7 @@
     EXPECT_CALL(platform_, GetGroupId("chronos-access", _))
       .WillOnce(DoAll(SetArgumentPointee<1>(shared_gid_),
                       Return(true)));
-    return mount_->Init();
+    return mount_->Init(&platform_, &crypto_);
   }
 
   bool LoadSerializedKeyset(const chromeos::Blob& contents,
@@ -187,7 +192,9 @@
   gid_t shared_gid_;
   NiceMock<MockPlatform> platform_;
   NiceMock<MockTpm> tpm_;
+  NiceMock<MockTpmInit> tpm_init_;
   NiceMock<MockHomeDirs> homedirs_;
+  NiceMock<MockCrypto> crypto_;
   MockChapsClientFactory chaps_client_factory_;
   scoped_refptr<Mount> mount_;
 
@@ -222,7 +229,7 @@
                     Return(true)));
   EXPECT_CALL(platform_, GetGroupId("chronos-access", _))
     .WillOnce(DoAll(SetArgumentPointee<1>(1002), Return(true)));
-  EXPECT_FALSE(mount_->Init());
+  EXPECT_FALSE(mount_->Init(&platform_, &crypto_));
   ASSERT_FALSE(mount_->AreValid(up));
 }
 
@@ -384,8 +391,8 @@
         kLegacyDir("/legacy"),
         kRootUID(0), kRootGID(0), kChapsUID(1), kSharedGID(2),
         mount_(new Mount()) {
-    mount_->crypto()->set_platform(&platform_);
-    mount_->set_platform(&platform_);
+    crypto_.set_platform(&platform_);
+    mount_->Init(&platform_, &crypto_);
     mount_->chaps_user_ = kChapsUID;
     mount_->default_access_group_ = kSharedGID;
     // By default, set stats to the expected values.
@@ -438,6 +445,7 @@
 
   scoped_refptr<Mount> mount_;
   NiceMock<MockPlatform> platform_;
+  NiceMock<MockCrypto> crypto_;
 
  private:
   void InitStat(struct stat* s, mode_t mode, uid_t uid, gid_t gid) {
@@ -542,6 +550,9 @@
 }
 
 TEST_F(MountTest, CheckChapsDirectoryMigration) {
+  EXPECT_CALL(platform_, DirectoryExists(kImageDir))
+    .WillRepeatedly(Return(true));
+
   // Configure stub methods.
   EXPECT_CALL(platform_, Copy(_, _))
       .WillRepeatedly(Return(true));
@@ -586,6 +597,7 @@
   EXPECT_CALL(platform_, SetOwnership("/fake", 1, 2)).Times(1);
   EXPECT_CALL(platform_, SetPermissions("/fake", 0123)).Times(1);
 
+  DoMountInit();
   EXPECT_TRUE(mount_->CheckChapsDirectory("/fake", "/fake_legacy"));
 }
 
@@ -594,14 +606,12 @@
   // Creates a cryptohome and tests credentials.
   HomeDirs homedirs;
   homedirs.set_shadow_root(kImageDir);
-  homedirs.set_platform(&platform_);
-  homedirs.set_crypto(mount_->crypto());
 
   TestUser *user = &helper_.users[0];
   UsernamePasskey up(user->username, user->passkey);
 
   EXPECT_TRUE(DoMountInit());
-  EXPECT_TRUE(homedirs.Init());
+  EXPECT_TRUE(homedirs.Init(&platform_, mount_->crypto()));
 
   // TODO(wad) Make this into a UserDoesntExist() helper.
   EXPECT_CALL(platform_, FileExists(user->image_path))
@@ -659,31 +669,34 @@
   // Create a Mount instance that points to a good shadow root, test that it
   // properly re-authenticates against the first key.
   mount_->set_use_tpm(true);
-  mount_->crypto()->set_use_tpm(true);
+  crypto_.set_use_tpm(true);
 
   HomeDirs homedirs;
   homedirs.set_shadow_root(kImageDir);
-  homedirs.set_platform(&platform_);
-  homedirs.set_crypto(mount_->crypto());
 
   TestUser *user = &helper_.users[0];
   UsernamePasskey up(user->username, user->passkey);
 
-  EXPECT_CALL(tpm_, Init(_, _))
+  EXPECT_CALL(tpm_init_, HasCryptohomeKey())
+    .WillOnce(Return(false))
     .WillRepeatedly(Return(true));
+  EXPECT_CALL(tpm_init_, SetupTpm(true))
+    .WillOnce(Return(true))  // This is by crypto.Init() and
+    .WillOnce(Return(true)); // because we forced HasCryptohomeKey to false once
+  crypto_.Init(&tpm_init_);
+
   EXPECT_CALL(tpm_, IsEnabled())
     .WillRepeatedly(Return(true));
   EXPECT_CALL(tpm_, IsOwned())
     .WillRepeatedly(Return(true));
-  EXPECT_CALL(tpm_, IsConnected())
-    .WillRepeatedly(Return(true));
 
   EXPECT_TRUE(DoMountInit());
-  EXPECT_TRUE(homedirs.Init());
+  EXPECT_TRUE(homedirs.Init(&platform_, mount_->crypto()));
 
   // Load the pre-generated keyset
   std::string key_path = mount_->GetUserLegacyKeyFileForUser(
       up.GetObfuscatedUsername(helper_.system_salt), 0);
+  EXPECT_TRUE(key_path.size() > 0);
   cryptohome::SerializedVaultKeyset serialized;
   EXPECT_TRUE(serialized.ParseFromArray(
                   static_cast<const unsigned char*>(&user->credentials[0]),
@@ -728,11 +741,11 @@
     .WillOnce(Return(true));
 
   // Create the "TPM-wrapped" value by letting it save the plaintext.
-  EXPECT_CALL(tpm_, Encrypt(_, _, _, _))
+  EXPECT_CALL(tpm_, EncryptBlob(_, _, _, _, _, _))
     .WillRepeatedly(Invoke(TpmPassthroughEncrypt));
   chromeos::SecureBlob fake_pub_key("A", 1);
-  EXPECT_CALL(tpm_, GetPublicKeyHash(_))
-    .WillRepeatedly(DoAll(SetArgumentPointee<0>(fake_pub_key),
+  EXPECT_CALL(tpm_, GetPublicKeyHash(_, _, _))
+    .WillRepeatedly(DoAll(SetArgumentPointee<2>(fake_pub_key),
                           Return(Tpm::RetryNone)));
 
   chromeos::Blob migrated_keyset;
@@ -771,7 +784,7 @@
   EXPECT_CALL(platform_, ReadFile(user->salt_path, _))
     .WillRepeatedly(DoAll(SetArgumentPointee<1>(user->user_salt),
                           Return(true)));
-  EXPECT_CALL(tpm_, Decrypt(_, _, _, _))
+  EXPECT_CALL(tpm_, DecryptBlob(_, _, _, _, _, _))
     .WillRepeatedly(Invoke(TpmPassthroughDecrypt));
 
     MockFileEnumerator* files = new MockFileEnumerator();
diff --git a/platform.cc b/platform.cc
index 6586c8f..a86897b 100644
--- a/platform.cc
+++ b/platform.cc
@@ -261,7 +261,7 @@
   FilePath fd_dirpath = pid_path.Append("fd");
 
   base::FileEnumerator fd_dir_enum(fd_dirpath, false,
-                                        base::FileEnumerator::FILES);
+                                   base::FileEnumerator::FILES);
 
   std::set<std::string> open_files;
   // List open file descriptors
@@ -316,7 +316,7 @@
     FilePath fd_dirpath = pid_path.Append("fd");
 
     base::FileEnumerator fd_dir_enum(fd_dirpath, false,
-                                          base::FileEnumerator::FILES);
+                                     base::FileEnumerator::FILES);
 
     // List open file descriptors
     for (FilePath fd_path = fd_dir_enum.Next();
diff --git a/service.cc b/service.cc
index efafa88..375baba 100644
--- a/service.cc
+++ b/service.cc
@@ -245,7 +245,7 @@
       platform_(default_platform_.get()),
       crypto_(new Crypto(platform_)),
       tpm_(Tpm::GetSingleton()),
-      default_tpm_init_(new TpmInit(platform_)),
+      default_tpm_init_(new TpmInit(tpm_, platform_)),
       tpm_init_(default_tpm_init_.get()),
       default_pkcs11_init_(new Pkcs11Init()),
       pkcs11_init_(default_pkcs11_init_.get()),
@@ -446,11 +446,10 @@
   chromeos_metrics::TimerReporter::set_metrics_lib(&metrics_lib_);
 
   crypto_->set_use_tpm(use_tpm_);
-  if (!crypto_->Init())
+  if (!crypto_->Init(tpm_init_))
     return false;
 
-  homedirs_->set_crypto(crypto_);
-  if (!homedirs_->Init())
+  if (!homedirs_->Init(platform_, crypto_))
     return false;
 
   // If the TPM is unowned or doesn't exist, it's safe for
@@ -464,12 +463,11 @@
   // Pass in all the shared dependencies here rather than
   // needing to always get the Attestation object to set them
   // during testing.
-  attestation_->Initialize(tpm_, platform_, crypto_, install_attrs_);
+  attestation_->Initialize(tpm_, tpm_init_, platform_, crypto_, install_attrs_);
 
   // TODO(wad) Determine if this should only be called if
   //           tpm->IsEnabled() is true.
   if (tpm_ && initialize_tpm_) {
-    tpm_init_->set_tpm(tpm_);
     tpm_init_->Init(this);
     if (!SeedUrandom()) {
       LOG(ERROR) << "FAILED TO SEED /dev/urandom AT START";
@@ -568,7 +566,7 @@
   }
 
   // Init can fail without making the interface inconsistent so we're okay here.
-  install_attrs_->Init();
+  install_attrs_->Init(tpm_init_);
 
   // Check if the machine is enterprise owned and report to mount_ then.
   DetectEnterpriseOwnership();
@@ -612,7 +610,7 @@
 
 bool Service::SeedUrandom() {
   SecureBlob random;
-  if (!tpm_init_->GetRandomData(kDefaultRandomSeedLength, &random)) {
+  if (!tpm_->GetRandomData(kDefaultRandomSeedLength, &random)) {
     LOG(ERROR) << "Could not get random data from the TPM";
     return false;
   }
@@ -2059,7 +2057,7 @@
   if (!tpm_init_->HasInitializeBeenCalled()) {
     timer_collection_->UpdateTimer(TimerCollection::kTpmTakeOwnershipTimer,
                                    true);
-    tpm_init_->StartInitializeTpm();
+    tpm_init_->AsyncInitializeTpm();
   }
   return TRUE;
 }
@@ -2666,7 +2664,26 @@
   for (MountMap::iterator it = mounts_.begin(); it != mounts_.end(); it++)
     mounts->Append(it->second->GetStatus());
   base::Value* attrs = install_attrs_->GetStatus();
-  base::Value* tpm = tpm_->GetStatusValue(tpm_init_);
+
+  Tpm::TpmStatusInfo tpm_status_info;
+  tpm_->GetStatus(tpm_init_->GetCryptohomeContext(),
+                  tpm_init_->GetCryptohomeKey(),
+                  &tpm_status_info);
+  base::DictionaryValue* tpm = new base::DictionaryValue();
+  tpm->SetBoolean("can_connect", tpm_status_info.CanConnect);
+  tpm->SetBoolean("can_load_srk", tpm_status_info.CanLoadSrk);
+  tpm->SetBoolean("can_load_srk_pubkey", tpm_status_info.CanLoadSrkPublicKey);
+  tpm->SetBoolean("has_cryptohome_key", tpm_status_info.HasCryptohomeKey);
+  tpm->SetBoolean("can_encrypt", tpm_status_info.CanEncrypt);
+  tpm->SetBoolean("can_decrypt", tpm_status_info.CanDecrypt);
+  tpm->SetBoolean("has_context", tpm_status_info.ThisInstanceHasContext);
+  tpm->SetBoolean("has_key_handle", tpm_status_info.ThisInstanceHasKeyHandle);
+  tpm->SetInteger("last_error", tpm_status_info.LastTpmError);
+
+  tpm->SetBoolean("enabled", tpm_->IsEnabled());
+  tpm->SetBoolean("owned", tpm_->IsOwned());
+  tpm->SetBoolean("being_owned", tpm_->IsBeingOwned());
+
   dv.Set("mounts", mounts);
   dv.Set("installattrs", attrs);
   dv.Set("tpm", tpm);
@@ -2720,7 +2737,7 @@
   mounts_lock_.Acquire();
   if (mounts_.count(username) == 0U) {
     m = mount_factory_->New();
-    m->Init();
+    m->Init(platform_, crypto_);
     m->set_enterprise_owned(enterprise_owned_);
     m->set_legacy_mount(legacy_mount_);
     mounts_[username] = m;
diff --git a/service.h b/service.h
index 99c1d19..509379a 100644
--- a/service.h
+++ b/service.h
@@ -19,6 +19,7 @@
 #include <metrics/metrics_library.h>
 #include <metrics/timer.h>
 
+#include "attestation.h"
 #include "cryptohome_event_source.h"
 #include "dbus_transition.h"
 #include "install_attributes.h"
diff --git a/service_unittest.cc b/service_unittest.cc
index c15d963..6f3cc70 100644
--- a/service_unittest.cc
+++ b/service_unittest.cc
@@ -93,8 +93,6 @@
 TEST_F(ServiceInterfaceTest, CheckKeySuccessTest) {
   MockHomeDirs homedirs;
   scoped_refptr<MockMount> mount = new MockMount();
-  EXPECT_CALL(homedirs, Init())
-      .WillOnce(Return(true));
   EXPECT_CALL(homedirs, FreeDiskSpace())
       .WillOnce(Return(true));
   EXPECT_CALL(*mount, AreSameUser(_))
@@ -114,6 +112,9 @@
   service.set_platform(&platform);
   service.set_chaps_client(&chaps);
   service.set_initialize_tpm(false);
+  EXPECT_CALL(homedirs, Init(&platform, service.crypto()))
+    .WillOnce(Return(true));
+
   service.Initialize();
   gboolean out = FALSE;
   GError *error = NULL;
@@ -131,8 +132,6 @@
 
   void SetUp() {
     mount_ = new MockMount();
-    EXPECT_CALL(homedirs_, Init())
-        .WillOnce(Return(true));
     EXPECT_CALL(homedirs_, FreeDiskSpace())
         .WillOnce(Return(true));
 
@@ -144,6 +143,8 @@
     service_.set_platform(&platform_);
     service_.set_chaps_client(&chaps_);
     service_.set_initialize_tpm(false);
+    EXPECT_CALL(homedirs_, Init(&platform_, service_.crypto()))
+        .WillOnce(Return(true));
     service_.Initialize();
   }
   void TearDown() {
@@ -285,9 +286,6 @@
   user->InjectKeyset(&platform);
 
   HomeDirs homedirs;
-  homedirs.crypto()->set_tpm(&tpm);
-  homedirs.crypto()->set_use_tpm(false);
-  homedirs.crypto()->set_platform(&platform);
   homedirs.set_shadow_root(kImageDir);
   homedirs.set_platform(&platform);
   homedirs.set_policy_provider(new policy::PolicyProvider(
@@ -405,13 +403,15 @@
   MockHomeDirs homedirs;
   Service service;
   service.set_homedirs(&homedirs);
+  NiceMock<MockPlatform> platform;
+  service.set_platform(&platform);
   NiceMock<MockInstallAttributes> attrs;
   service.set_install_attrs(&attrs);
   service.set_initialize_tpm(false);
 
   // Service will schedule periodic clean-ups. Wait a bit and make
   // sure that we had at least 3 executed.
-  EXPECT_CALL(homedirs, Init())
+  EXPECT_CALL(homedirs, Init(&platform, service.crypto()))
       .WillOnce(Return(true));
   EXPECT_CALL(homedirs, FreeDiskSpace())
       .Times(::testing::AtLeast(3));
@@ -441,9 +441,11 @@
   service.set_initialize_tpm(false);
   NiceMock<MockAttestation> attest;
   service.set_attestation(&attest);
+  NiceMock<MockPlatform> platform;
+  service.set_platform(&platform);
 
   // Service will schedule first cleanup right after its init.
-  EXPECT_CALL(homedirs, Init())
+  EXPECT_CALL(homedirs, Init(&platform, service.crypto()))
       .WillOnce(Return(true));
   EXPECT_CALL(homedirs, FreeDiskSpace())
       .Times(1);
@@ -563,7 +565,7 @@
 
   service_.set_mount_factory(&f);
 
-  EXPECT_CALL(homedirs_, Init())
+  EXPECT_CALL(homedirs_, Init(&platform_, service_.crypto()))
     .WillOnce(Return(true));
 
   EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
@@ -572,7 +574,7 @@
 
   ASSERT_TRUE(service_.Initialize());
 
-  EXPECT_CALL(*m, Init())
+  EXPECT_CALL(*m, Init(&platform_, service_.crypto()))
     .WillOnce(Return(true));
   EXPECT_CALL(*m, MountCryptohome(_, _, _))
     .WillOnce(Return(true));
@@ -741,7 +743,7 @@
 
     g_error_ = NULL;
     // Fast path through Initialize()
-    EXPECT_CALL(homedirs_, Init())
+    EXPECT_CALL(homedirs_, Init(&platform_, service_.crypto()))
         .WillOnce(Return(true));
     // Skip the CleanUpStaleMounts bit.
     EXPECT_CALL(platform_, GetMountsBySourcePrefix(_, _))
diff --git a/stub_tpm.h b/stub_tpm.h
index b651efb..617ad95 100644
--- a/stub_tpm.h
+++ b/stub_tpm.h
@@ -4,7 +4,6 @@
 #include <stdio.h>
 #include <unistd.h>
 
-#include "platform.h"
 #include "tpm.h"
 
 namespace cryptohome {
@@ -15,7 +14,6 @@
   virtual ~StubTpm() { }
 
   // See tpm.h for comments
-  virtual bool Init(Platform* platform, bool open_key) { return false; }
   virtual bool Connect(TpmRetryAction* retry_action) { return false; }
   virtual bool IsConnected() { return false; }
   virtual bool IsEnabled() const { return false; }
@@ -28,7 +26,6 @@
   virtual void Disconnect() { }
   virtual bool GetOwnerPassword(
     chromeos::Blob* owner_password) { return false; }
-  virtual void RemoveOwnerDependency(TpmOwnerDependency dependency) { }
   virtual bool Encrypt(const chromeos::SecureBlob& plaintext,
                        const chromeos::SecureBlob& key,
                        chromeos::SecureBlob* ciphertext,
diff --git a/tpm.cc b/tpm.cc
index 0dfd04e..ba026b2 100644
--- a/tpm.cc
+++ b/tpm.cc
@@ -21,8 +21,6 @@
 #include <trousers/trousers.h>
 
 #include "cryptolib.h"
-#include "platform.h"
-#include "tpm_init.h"
 
 using base::PlatformThread;
 using chromeos::SecureBlob;
@@ -59,27 +57,16 @@
 const unsigned int kDefaultTpmRsaKeyBits = 2048;
 const unsigned int kDefaultTpmRsaKeyFlag = TSS_KEY_SIZE_2048;
 const unsigned int kDefaultDiscardableWrapPasswordLength = 32;
-const char kDefaultCryptohomeKeyFile[] = "/home/.shadow/cryptohome.key";
-const TSS_UUID kCryptohomeWellKnownUuid = {0x0203040b, 0, 0, 0, 0,
-                                           {0, 9, 8, 1, 0, 3}};
+
 const char* kWellKnownSrkTmp = "1234567890";
-const int kOwnerPasswordLength = 12;
-const int kMaxTimeoutRetries = 5;
-const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled";
-const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned";
-const char* kTpmOwnedFileOld = "/var/lib/.tpm_owned";
-const char* kTpmStatusFileOld = "/var/lib/.tpm_status";
-const char* kTpmOwnedFile = "/mnt/stateful_partition/.tpm_owned";
-const char* kTpmStatusFile = "/mnt/stateful_partition/.tpm_status";
-const char* kOpenCryptokiPath = "/var/lib/opencryptoki";
 const unsigned int kTpmConnectRetries = 10;
 const unsigned int kTpmConnectIntervalMs = 100;
-const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET;
 const unsigned int kTpmBootPCR = 0;
 const unsigned int kTpmPCRLocality = 1;
 const int kDelegateSecretSize = 20;
 const int kDelegateFamilyLabel = 1;
 const int kDelegateEntryLabel = 2;
+
 // This error is returned when an attempt is made to use the SRK but it does not
 // yet exist because the TPM has not been owned.
 const TSS_RESULT kKeyNotFoundError = (TSS_E_PS_KEY_NOTFOUND | TSS_LAYER_TCS);
@@ -99,149 +86,16 @@
 Tpm::Tpm()
     : initialized_(false),
       srk_auth_(kDefaultSrkAuth, sizeof(kDefaultSrkAuth)),
-      context_handle_(0),
-      key_handle_(0),
       owner_password_(),
       password_sync_lock_(),
       is_disabled_(true),
       is_owned_(false),
-      is_being_owned_(false),
-      platform_(NULL) {
-}
-
-Tpm::~Tpm() {
-  Disconnect();
-}
-
-bool Tpm::Init(Platform* platform, bool open_key) {
-  if (initialized_) {
-    return false;
-  }
-  initialized_ = true;
-  DCHECK(platform);
-  platform_ = platform;
-
+      is_being_owned_(false) {
   metrics_.reset(new MetricsLibrary());
   metrics_->Init();
-
-  // Migrate any old status files from old location to new location.
-  if (!platform_->FileExists(kTpmOwnedFile) &&
-      platform_->FileExists(kTpmOwnedFileOld)) {
-    platform_->Move(kTpmOwnedFileOld, kTpmOwnedFile);
-  }
-  if (!platform_->FileExists(kTpmStatusFile) &&
-      platform_->FileExists(kTpmStatusFileOld)) {
-    platform_->Move(kTpmStatusFileOld, kTpmStatusFile);
-  }
-
-  // Checking disabled and owned either via sysfs or via TSS calls will block if
-  // ownership is being taken by another thread or process.  So for this to work
-  // well, Tpm::Init() needs to be called before InitializeTpm() is called.  At
-  // that point, the public API for Tpm only checks these booleans, so other
-  // threads can check without being blocked.  InitializeTpm() will reset the
-  // is_owned_ bit on success.
-  bool successful_check = false;
-  if (platform_->FileExists(kTpmCheckEnabledFile)) {
-    is_disabled_ = IsDisabledCheckViaSysfs();
-    is_owned_ = IsOwnedCheckViaSysfs();
-    successful_check = true;
-  } else {
-    TSS_HCONTEXT context_handle;
-    TSS_RESULT result;
-    if (OpenAndConnectTpm(&context_handle, &result)) {
-      bool enabled = false;
-      bool owned = false;
-      IsEnabledOwnedCheckViaContext(context_handle, &enabled, &owned);
-      DisconnectContext(context_handle);
-      is_disabled_ = !enabled;
-      is_owned_ = owned;
-      successful_check = true;
-    }
-  }
-  if (successful_check && !is_owned_) {
-    platform_->DeleteFile(kOpenCryptokiPath, true);
-    platform_->DeleteFile(kTpmOwnedFile, false);
-    platform_->DeleteFile(kTpmStatusFile, false);
-  }
-  if (successful_check && is_owned_) {
-    if (!platform_->FileExists(kTpmOwnedFile)) {
-      chromeos::Blob empty_blob(0);
-      platform_->WriteFile(kTpmOwnedFile, empty_blob);
-    }
-  }
-  TpmStatus tpm_status;
-  if (LoadTpmStatus(&tpm_status)) {
-    if (tpm_status.has_owner_password()) {
-      SecureBlob local_owner_password;
-      if (LoadOwnerPassword(tpm_status, &local_owner_password)) {
-        password_sync_lock_.Acquire();
-        owner_password_.assign(local_owner_password.begin(),
-                               local_owner_password.end());
-        password_sync_lock_.Release();
-      }
-    }
-  }
-
-  if (open_key && key_handle_ == 0) {
-    Tpm::TpmRetryAction retry_action;
-    return Connect(&retry_action);
-  }
-
-  return true;
 }
 
-bool Tpm::Connect(TpmRetryAction* retry_action) {
-  // TODO(fes): Check the status of enabled, owned, being_owned first.
-  *retry_action = Tpm::RetryNone;
-  if (key_handle_ == 0) {
-    TSS_RESULT result;
-    TSS_HCONTEXT context_handle;
-    if (!OpenAndConnectTpm(&context_handle, &result)) {
-      context_handle_ = 0;
-      key_handle_ = 0;
-      *retry_action = HandleError(result);
-      TPM_LOG(ERROR, result) << "Error connecting to the TPM";
-      return false;
-    }
-
-    TSS_HKEY key_handle;
-    if (!LoadOrCreateCryptohomeKey(context_handle, false, &key_handle,
-                                   &result)) {
-      context_handle_ = 0;
-      key_handle_ = 0;
-      *retry_action = HandleError(result);
-      Tspi_Context_Close(context_handle);
-      if (result == kKeyNotFoundError) {
-        TPM_LOG(WARNING, result)
-            << "Cannot load / create the cryptohome TPM key. "
-            << "This is normal when the TPM is not owned.";
-      } else {
-        TPM_LOG(ERROR, result) << "Error loading the cryptohome TPM key";
-      }
-      return false;
-    }
-
-    key_handle_ = key_handle;
-    context_handle_ = context_handle;
-  }
-
-  return true;
-}
-
-bool Tpm::IsConnected() {
-  return (key_handle_ != 0);
-}
-
-void Tpm::Disconnect() {
-  if (key_handle_) {
-    Tspi_Context_CloseObject(context_handle_, key_handle_);
-    key_handle_ = 0;
-  }
-  if (context_handle_) {
-    Tspi_Context_Close(context_handle_);
-    context_handle_ = 0;
-  }
-}
+Tpm::~Tpm() { }
 
 TSS_HCONTEXT Tpm::ConnectContext() {
   TSS_RESULT result;
@@ -253,12 +107,6 @@
   return context_handle;
 }
 
-void Tpm::DisconnectContext(TSS_HCONTEXT context_handle) {
-  if (context_handle) {
-    Tspi_Context_Close(context_handle);
-  }
-}
-
 bool Tpm::ConnectContextAsOwner(TSS_HCONTEXT* context, TSS_HTPM* tpm) {
   *context = 0;
   *tpm = 0;
@@ -332,10 +180,12 @@
 }
 
 
-void Tpm::GetStatus(bool check_crypto, Tpm::TpmStatusInfo* status) {
+void Tpm::GetStatus(TSS_HCONTEXT context,
+                    TSS_HKEY key_handle,
+                    Tpm::TpmStatusInfo* status) {
   memset(status, 0, sizeof(Tpm::TpmStatusInfo));
-  status->ThisInstanceHasContext = (context_handle_ != 0);
-  status->ThisInstanceHasKeyHandle = (key_handle_ != 0);
+  status->ThisInstanceHasContext = (context != 0);
+  status->ThisInstanceHasKeyHandle = (key_handle != 0);
   ScopedTssContext context_handle;
   // Check if we can connect
   TSS_RESULT result;
@@ -363,15 +213,10 @@
   }
   status->CanLoadSrkPublicKey = true;
 
-  // Check the Cryptohome key
-  ScopedTssKey key_handle(context_handle);
-  if (!LoadCryptohomeKey(context_handle, key_handle.ptr(), &result)) {
-    status->LastTpmError = result;
-    return;
-  }
-  status->HasCryptohomeKey = true;
+  // Check the Cryptohome key by using what we have been told.
+  status->HasCryptohomeKey = (context != 0) && (key_handle != 0);
 
-  if (check_crypto) {
+  if (status->HasCryptohomeKey) {
     // Check encryption (we don't care about the contents, just whether or not
     // there was an error)
     SecureBlob data(16);
@@ -384,269 +229,21 @@
     memset(data_out.data(), 'D', data_out.size());
     SecureBlob key;
     CryptoLib::PasskeyToAesKey(password, salt, 13, &key, NULL);
-    if (!EncryptBlob(context_handle, key_handle, data, key, &data_out,
-                     &result)) {
-      status->LastTpmError = result;
+    TSS_RESULT result;
+    if (!EncryptBlob(context, key_handle, data, key, &data_out, &result)) {
       return;
     }
     status->CanEncrypt = true;
 
     // Check decryption (we don't care about the contents, just whether or not
     // there was an error)
-    if (!DecryptBlob(context_handle, key_handle, data_out, key, &data,
-                     &result)) {
-      status->LastTpmError = result;
+    if (!DecryptBlob(context, key_handle, data_out, key, &data, &result)) {
       return;
     }
     status->CanDecrypt = true;
   }
 }
 
-bool Tpm::CreateCryptohomeKey(TSS_HCONTEXT context_handle, bool create_in_tpm,
-                              TSS_RESULT* result) {
-  *result = TSS_SUCCESS;
-
-  // Load the Storage Root Key
-  ScopedTssKey srk_handle(context_handle);
-  if (!LoadSrk(context_handle, srk_handle.ptr(), result)) {
-    if (*result != kKeyNotFoundError) {
-      TPM_LOG(INFO, *result) << "CreateCryptohomeKey: Cannot load SRK";
-    }
-    return false;
-  }
-
-  // Make sure we can get the public key for the SRK.  If not, then the TPM
-  // is not available.
-  unsigned int size_n;
-  ScopedTssMemory public_srk(context_handle);
-  if (TPM_ERROR(*result = Tspi_Key_GetPubKey(srk_handle, &size_n,
-                                             public_srk.ptr()))) {
-    TPM_LOG(INFO, *result) << "CreateCryptohomeKey: Cannot load SRK pub key";
-    return false;
-  }
-
-  // Create the key object
-  TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_VOLATILE;
-  if (!create_in_tpm) {
-    init_flags |= TSS_KEY_MIGRATABLE;
-    init_flags |= kDefaultTpmRsaKeyFlag;
-  }
-  ScopedTssKey local_key_handle(context_handle);
-  if (TPM_ERROR(*result = Tspi_Context_CreateObject(context_handle,
-                                                    TSS_OBJECT_TYPE_RSAKEY,
-                                                    init_flags,
-                                                    local_key_handle.ptr()))) {
-    TPM_LOG(ERROR, *result) << "Error calling Tspi_Context_CreateObject";
-    return false;
-  }
-
-  // Set the attributes
-  UINT32 sig_scheme = TSS_SS_RSASSAPKCS1V15_DER;
-  if (TPM_ERROR(*result = Tspi_SetAttribUint32(local_key_handle,
-                                               TSS_TSPATTRIB_KEY_INFO,
-                                               TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
-                                               sig_scheme))) {
-    TPM_LOG(ERROR, *result) << "Error calling Tspi_SetAttribUint32";
-    return false;
-  }
-
-  UINT32 enc_scheme = TSS_ES_RSAESPKCSV15;
-  if (TPM_ERROR(*result = Tspi_SetAttribUint32(local_key_handle,
-                                               TSS_TSPATTRIB_KEY_INFO,
-                                               TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
-                                               enc_scheme))) {
-    TPM_LOG(ERROR, *result) << "Error calling Tspi_SetAttribUint32";
-    return false;
-  }
-
-  // Create a new system-wide key for cryptohome
-  if (create_in_tpm) {
-    if (TPM_ERROR(*result = Tspi_Key_CreateKey(local_key_handle,
-                                               srk_handle,
-                                               0))) {
-      TPM_LOG(ERROR, *result) << "Error calling Tspi_Key_CreateKey";
-      return false;
-    }
-  } else {
-    ScopedTssPolicy policy_handle(context_handle);
-    if (TPM_ERROR(*result = Tspi_Context_CreateObject(context_handle,
-                                                      TSS_OBJECT_TYPE_POLICY,
-                                                      TSS_POLICY_MIGRATION,
-                                                      policy_handle.ptr()))) {
-      TPM_LOG(ERROR, *result) << "Error creating policy object";
-      return false;
-    }
-
-    // Set a random migration policy password, and discard it.  The key will not
-    // be migrated, but to create the key outside of the TPM, we have to do it
-    // this way.
-    SecureBlob migration_password(kDefaultDiscardableWrapPasswordLength);
-    CryptoLib::GetSecureRandom(
-        static_cast<unsigned char*>(migration_password.data()),
-        migration_password.size());
-    if (TPM_ERROR(*result = Tspi_Policy_SetSecret(policy_handle,
-                            TSS_SECRET_MODE_PLAIN,
-                            migration_password.size(),
-                            static_cast<BYTE*>(migration_password.data())))) {
-      TPM_LOG(ERROR, *result) << "Error setting migration policy password";
-      return false;
-    }
-
-    if (TPM_ERROR(*result = Tspi_Policy_AssignToObject(policy_handle,
-                                                       local_key_handle))) {
-      TPM_LOG(ERROR, *result) << "Error assigning migration policy";
-      return false;
-    }
-
-    SecureBlob n;
-    SecureBlob p;
-    if (!CryptoLib::CreateRsaKey(kDefaultTpmRsaKeyBits, &n, &p)) {
-      LOG(ERROR) << "Error creating RSA key";
-      return false;
-    }
-
-    if (TPM_ERROR(*result = Tspi_SetAttribData(local_key_handle,
-                                             TSS_TSPATTRIB_RSAKEY_INFO,
-                                             TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
-                                             n.size(),
-                                             static_cast<BYTE *>(n.data())))) {
-      TPM_LOG(ERROR, *result) << "Error setting RSA modulus";
-      return false;
-    }
-
-    if (TPM_ERROR(*result = Tspi_SetAttribData(local_key_handle,
-                                             TSS_TSPATTRIB_KEY_BLOB,
-                                             TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY,
-                                             p.size(),
-                                             static_cast<BYTE *>(p.data())))) {
-      TPM_LOG(ERROR, *result) << "Error setting private key";
-      return false;
-    }
-
-    if (TPM_ERROR(*result = Tspi_Key_WrapKey(local_key_handle,
-                                             srk_handle,
-                                             0))) {
-      TPM_LOG(ERROR, *result) << "Error wrapping RSA key";
-      return false;
-    }
-  }
-
-  if (!SaveCryptohomeKey(context_handle, local_key_handle, result)) {
-    LOG(ERROR) << "Couldn't save cryptohome key";
-    return false;
-  }
-
-  LOG(INFO) << "Created new cryptohome key.";
-  return true;
-}
-
-bool Tpm::LoadCryptohomeKey(TSS_HCONTEXT context_handle,
-                            TSS_HKEY* key_handle, TSS_RESULT* result) {
-  // Load the Storage Root Key
-  ScopedTssKey srk_handle(context_handle);
-  if (!LoadSrk(context_handle, srk_handle.ptr(), result)) {
-    if (*result != kKeyNotFoundError) {
-      TPM_LOG(INFO, *result) << "LoadCryptohomeKey: Cannot load SRK";
-    }
-    return false;
-  }
-
-  // Make sure we can get the public key for the SRK.  If not, then the TPM
-  // is not available.
-  unsigned int size_n;
-  ScopedTssMemory public_srk(context_handle);
-  if (TPM_ERROR(*result = Tspi_Key_GetPubKey(srk_handle, &size_n,
-                                             public_srk.ptr()))) {
-    TPM_LOG(INFO, *result) << "LoadCryptohomeKey: Cannot load SRK public key";
-    return false;
-  }
-
-  // First, try loading the key from the key file
-  SecureBlob raw_key;
-  if (platform_->ReadFile(kDefaultCryptohomeKeyFile, &raw_key)) {
-    if (TPM_ERROR(*result = Tspi_Context_LoadKeyByBlob(
-                                    context_handle,
-                                    srk_handle,
-                                    raw_key.size(),
-                                    vector_as_array(&raw_key),
-                                    key_handle))) {
-      // If the error is expected to be transient, return now.
-      if (IsTransient(*result)) {
-        TPM_LOG(INFO, *result) << "LoadCryptohomeKey: Cannot load key " \
-                                << "from blob";
-        return false;
-      }
-    } else {
-      SecureBlob pub_key;
-      // Make sure that we can get the public key
-      if (GetPublicKeyBlob(context_handle, *key_handle, &pub_key, result)) {
-        return true;
-      }
-      // Otherwise, close the key and fall through
-      Tspi_Context_CloseObject(context_handle, *key_handle);
-      if (IsTransient(*result)) {
-        TPM_LOG(INFO, *result) << "LoadCryptohomeKey: closed object";
-        return false;
-      }
-    }
-  }
-
-  // Then try loading the key by the UUID (this is a legacy upgrade path)
-  if (TPM_ERROR(*result = Tspi_Context_LoadKeyByUUID(context_handle,
-                                                     TSS_PS_TYPE_SYSTEM,
-                                                     kCryptohomeWellKnownUuid,
-                                                     key_handle))) {
-    // If the error is expected to be transient, return now.
-    if (IsTransient(*result)) {
-      TPM_LOG(INFO, *result) << "LoadCryptohomeKey: failed LoadKeyByUUID";
-      return false;
-    }
-  } else {
-    SecureBlob pub_key;
-    // Make sure that we can get the public key
-    if (GetPublicKeyBlob(context_handle, *key_handle, &pub_key, result)) {
-      // Save the cryptohome key to the well-known location
-      if (!SaveCryptohomeKey(context_handle, *key_handle, result)) {
-        LOG(ERROR) << "Couldn't save cryptohome key";
-        Tspi_Context_CloseObject(context_handle, *key_handle);
-        return false;
-      }
-      return true;
-    }
-    Tspi_Context_CloseObject(context_handle, *key_handle);
-  }
-
-  TPM_LOG(INFO, *result) << "LoadCryptohomeKey: could not load key";
-  return false;
-}
-
-bool Tpm::LoadOrCreateCryptohomeKey(TSS_HCONTEXT context_handle,
-                                    bool create_in_tpm,
-                                    TSS_HKEY* key_handle,
-                                    TSS_RESULT* result) {
-  *result = TSS_SUCCESS;
-
-  // Try to load the cryptohome key.
-  if (LoadCryptohomeKey(context_handle, key_handle, result)) {
-    return true;
-  }
-
-  // If the error is expected to be transient, return now.
-  if (IsTransient(*result)) {
-    TPM_LOG(INFO, *result) << "Transient failure loading cryptohome key";
-    return false;
-  }
-
-  // Otherwise, the key couldn't be loaded, and it wasn't due to a transient
-  // error, so we must create the key.
-  if (CreateCryptohomeKey(context_handle, create_in_tpm, result)) {
-    if (LoadCryptohomeKey(context_handle, key_handle, result)) {
-      return true;
-    }
-  }
-  return false;
-}
-
 bool Tpm::IsTransient(TSS_RESULT result) {
   bool transient = false;
   switch (ERROR_CODE(result)) {
@@ -669,18 +266,15 @@
   switch (ERROR_CODE(result)) {
     case ERROR_CODE(TSS_E_COMM_FAILURE):
       LOG(ERROR) << "Communications failure with the TPM.";
-      Disconnect();
       status = Tpm::RetryCommFailure;
       break;
     case ERROR_CODE(TSS_E_INVALID_HANDLE):
       LOG(ERROR) << "Invalid handle to the TPM.";
-      Disconnect();
       status = Tpm::RetryCommFailure;
       break;
     // TODO(fes): We're considering this a communication failure for now.
     case ERROR_CODE(TCS_E_KM_LOADFAILED):
       LOG(ERROR) << "Key load failed; problem with parent key authorization.";
-      Disconnect();
       status = Tpm::RetryCommFailure;
       break;
     case ERROR_CODE(TPM_E_DEFEND_LOCK_RUNNING):
@@ -704,23 +298,6 @@
   return status;
 }
 
-bool Tpm::SaveCryptohomeKey(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                            TSS_RESULT* result) {
-  *result = TSS_SUCCESS;
-
-  SecureBlob raw_key;
-  if (!GetKeyBlob(context_handle, key_handle, &raw_key, result)) {
-    LOG(ERROR) << "Error getting key blob";
-    return false;
-  }
-  int previous_mask = platform_->SetMask(cryptohome::kDefaultUmask);
-  bool ok = platform_->WriteFile(kDefaultCryptohomeKeyFile, raw_key);
-  platform_->SetMask(previous_mask);
-  if (!ok)
-    LOG(ERROR) << "Error writing key file of desired size: " << raw_key.size();
-  return ok;
-}
-
 bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle, TSS_RESULT* result) {
   TSS_RESULT local_result;
   ScopedTssContext local_context_handle;
@@ -764,54 +341,12 @@
   return (*context_handle != 0);
 }
 
-bool Tpm::Encrypt(const SecureBlob& plaintext,
-                  const SecureBlob& key,
-                  SecureBlob* ciphertext,
-                  Tpm::TpmRetryAction* retry_action) {
-  *retry_action = Tpm::RetryNone;
-  if (!IsConnected()) {
-    if (!Connect(retry_action)) {
-      return false;
-    }
-  }
-
-  TSS_RESULT result = TSS_SUCCESS;
-  if (!EncryptBlob(context_handle_, key_handle_, plaintext, key, ciphertext,
-                   &result)) {
-    *retry_action = HandleError(result);
-    return false;
-  }
-  return true;
-}
-
-bool Tpm::Decrypt(const SecureBlob& ciphertext,
-                  const SecureBlob& key,
-                  SecureBlob* plaintext,
-                  Tpm::TpmRetryAction* retry_action) {
-  *retry_action = Tpm::RetryNone;
-  if (!IsConnected()) {
-    if (!Connect(retry_action)) {
-      return false;
-    }
-  }
-
-  TSS_RESULT result = TSS_SUCCESS;
-  if (!DecryptBlob(context_handle_, key_handle_, ciphertext, key, plaintext,
-                   &result)) {
-    *retry_action = HandleError(result);
-    return false;
-  }
-  return true;
-}
-
-Tpm::TpmRetryAction Tpm::GetPublicKeyHash(SecureBlob* hash) {
-  TpmRetryAction ret = Tpm::RetryNone;
-  if (!IsConnected() && !Connect(&ret))
-    return ret;
-
+Tpm::TpmRetryAction Tpm::GetPublicKeyHash(TSS_HCONTEXT context_handle,
+                                          TSS_HKEY key_handle,
+                                          SecureBlob* hash) {
   TSS_RESULT result = TSS_SUCCESS;
   SecureBlob pubkey;
-  if (!GetPublicKeyBlob(context_handle_, key_handle_, &pubkey, &result)) {
+  if (!GetPublicKeyBlob(context_handle, key_handle, &pubkey, &result)) {
     return HandleError(result);
   }
 
@@ -980,28 +515,8 @@
   return true;
 }
 
-bool Tpm::GetKeyBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                     SecureBlob* data_out, TSS_RESULT* result) {
-  *result = TSS_SUCCESS;
-
-  ScopedTssMemory blob(context_handle);
-  UINT32 blob_size;
-  if (TPM_ERROR(*result = Tspi_GetAttribData(key_handle, TSS_TSPATTRIB_KEY_BLOB,
-                                   TSS_TSPATTRIB_KEYBLOB_BLOB,
-                                   &blob_size, blob.ptr()))) {
-    TPM_LOG(ERROR, *result) << "Couldn't get key blob";
-    return false;
-  }
-
-  SecureBlob local_data(blob_size);
-  memcpy(local_data.data(), blob.value(), blob_size);
-  chromeos::SecureMemset(blob.value(), 0, blob_size);
-  data_out->swap(local_data);
-  return true;
-}
-
 bool Tpm::GetPublicKeyBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                           SecureBlob* data_out, TSS_RESULT* result) {
+                           SecureBlob* data_out, TSS_RESULT* result) const {
   *result = TSS_SUCCESS;
 
   ScopedTssMemory blob(context_handle);
@@ -1020,7 +535,7 @@
 }
 
 bool Tpm::LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle,
-                  TSS_RESULT* result) {
+                  TSS_RESULT* result) const {
   *result = TSS_SUCCESS;
 
   // Load the Storage Root Key
@@ -1051,10 +566,8 @@
       return false;
     }
 
-    *result = Tspi_Policy_SetSecret(srk_usage_policy,
-                                    TSS_SECRET_MODE_PLAIN,
-                                    srk_auth_.size(),
-                                    vector_as_array(&srk_auth_));
+    *result = Tspi_Policy_SetSecret(srk_usage_policy, TSS_SECRET_MODE_PLAIN,
+        srk_auth_.size(), const_cast<BYTE*>(vector_as_array(&srk_auth_)));
     if (TPM_ERROR(*result)) {
       return false;
     }
@@ -1064,55 +577,6 @@
   return true;
 }
 
-bool Tpm::IsDisabledCheckViaSysfs() {
-  std::string contents;
-  if (!platform_->ReadFileToString(kTpmCheckEnabledFile, &contents)) {
-    return false;
-  }
-  if (contents.size() < 1) {
-    return false;
-  }
-  return (contents[0] == '0');
-}
-
-bool Tpm::IsOwnedCheckViaSysfs() {
-  std::string contents;
-  if (!platform_->ReadFileToString(kTpmCheckOwnedFile, &contents)) {
-    return false;
-  }
-  if (contents.size() < 1) {
-    return false;
-  }
-  return (contents[0] != '0');
-}
-
-void Tpm::IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle,
-                                        bool* enabled, bool* owned) {
-  *enabled = false;
-  *owned = false;
-
-  TSS_RESULT result;
-  TSS_HTPM tpm_handle;
-  if (!GetTpm(context_handle, &tpm_handle)) {
-    return;
-  }
-
-  UINT32 sub_cap = TSS_TPMCAP_PROP_OWNER;
-  UINT32 cap_length = 0;
-  ScopedTssMemory cap(context_handle);
-  if (TPM_ERROR(result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY,
-                                       sizeof(sub_cap),
-                                       reinterpret_cast<BYTE*>(&sub_cap),
-                                       &cap_length, cap.ptr())) == 0) {
-    if (cap_length >= (sizeof(TSS_BOOL))) {
-      *enabled = true;
-      *owned = ((*(reinterpret_cast<TSS_BOOL*>(cap.value()))) != 0);
-    }
-  } else if (ERROR_CODE(result) == TPM_E_DISABLED) {
-    *enabled = false;
-  }
-}
-
 bool Tpm::CreateEndorsementKey(TSS_HCONTEXT context_handle) {
   TSS_RESULT result;
   TSS_HTPM tpm_handle;
@@ -1157,19 +621,6 @@
   return true;
 }
 
-void Tpm::CreateOwnerPassword(SecureBlob* password) {
-  // Generate a random owner password.  The default is a 12-character,
-  // hex-encoded password created from 6 bytes of random data.
-  SecureBlob random(kOwnerPasswordLength / 2);
-  CryptoLib::GetSecureRandom(static_cast<unsigned char*>(random.data()),
-                             random.size());
-  SecureBlob tpm_password(kOwnerPasswordLength);
-  CryptoLib::AsciiEncodeToBuffer(random,
-                                 static_cast<char*>(tpm_password.data()),
-                                 tpm_password.size());
-  password->swap(tpm_password);
-}
-
 bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries,
                         const SecureBlob& owner_password) {
   TSS_RESULT result;
@@ -1330,49 +781,6 @@
   return true;
 }
 
-bool Tpm::LoadOwnerPassword(const TpmStatus& tpm_status,
-                            chromeos::Blob* owner_password) {
-  if (!(tpm_status.flags() & TpmStatus::OWNED_BY_THIS_INSTALL)) {
-    return false;
-  }
-  if ((tpm_status.flags() & TpmStatus::USES_WELL_KNOWN_OWNER)) {
-    SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
-    memcpy(default_owner_password.data(), kTpmWellKnownPassword,
-           sizeof(kTpmWellKnownPassword));
-    owner_password->swap(default_owner_password);
-    return true;
-  }
-  if (!(tpm_status.flags() & TpmStatus::USES_RANDOM_OWNER) ||
-      !tpm_status.has_owner_password()) {
-    return false;
-  }
-
-  SecureBlob local_owner_password(tpm_status.owner_password().length());
-  tpm_status.owner_password().copy(
-      static_cast<char*>(local_owner_password.data()),
-      tpm_status.owner_password().length(), 0);
-  if (!Unseal(local_owner_password, owner_password)) {
-    LOG(ERROR) << "Failed to unseal the owner password.";
-    return false;
-  }
-  return true;
-}
-
-bool Tpm::StoreOwnerPassword(const chromeos::Blob& owner_password,
-                             TpmStatus* tpm_status) {
-  // Use PCR0 when sealing the data so that the owner password is only
-  // available in the current boot mode.  This helps protect the password from
-  // offline attacks until it has been presented and cleared.
-  SecureBlob sealed_password;
-  if (!SealToPCR0(owner_password, &sealed_password)) {
-    LOG(ERROR) << "StoreOwnerPassword: Failed to seal owner password.";
-    return false;
-  }
-  tpm_status->set_owner_password(sealed_password.data(),
-                                 sealed_password.size());
-  return true;
-}
-
 bool Tpm::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) {
   TSS_RESULT result;
   TSS_HTPM local_tpm_handle;
@@ -1481,140 +889,6 @@
   return result;
 }
 
-bool Tpm::InitializeTpm(bool* OUT_took_ownership) {
-  TpmStatus tpm_status;
-
-  if (!LoadTpmStatus(&tpm_status)) {
-    tpm_status.Clear();
-    tpm_status.set_flags(TpmStatus::NONE);
-  }
-
-  if (OUT_took_ownership) {
-    *OUT_took_ownership = false;
-  }
-
-  if (is_disabled_) {
-    return false;
-  }
-
-  ScopedTssContext context_handle;
-  if (!(*(context_handle.ptr()) = ConnectContext())) {
-    LOG(ERROR) << "Failed to connect to TPM";
-    return false;
-  }
-
-  SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
-  memcpy(default_owner_password.data(), kTpmWellKnownPassword,
-         sizeof(kTpmWellKnownPassword));
-
-  bool took_ownership = false;
-  if (!is_owned_) {
-    is_being_owned_ = true;
-    platform_->DeleteFile(kOpenCryptokiPath, true);
-    platform_->DeleteFile(kTpmOwnedFile, false);
-    platform_->DeleteFile(kTpmStatusFile, false);
-
-    if (!IsEndorsementKeyAvailable(context_handle)) {
-      if (!CreateEndorsementKey(context_handle)) {
-        LOG(ERROR) << "Failed to create endorsement key";
-        is_being_owned_ = false;
-        return false;
-      }
-    }
-
-    if (!IsEndorsementKeyAvailable(context_handle)) {
-      LOG(ERROR) << "Endorsement key is not available";
-      is_being_owned_ = false;
-      return false;
-    }
-
-    if (!TakeOwnership(context_handle, kMaxTimeoutRetries,
-                       default_owner_password)) {
-      LOG(ERROR) << "Take Ownership failed";
-      is_being_owned_ = false;
-      return false;
-    }
-
-    is_owned_ = true;
-    took_ownership = true;
-
-    tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
-                         TpmStatus::USES_WELL_KNOWN_OWNER |
-                         TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
-                         TpmStatus::ATTESTATION_NEEDS_OWNER);
-    tpm_status.clear_owner_password();
-    StoreTpmStatus(tpm_status);
-  }
-
-  if (OUT_took_ownership) {
-    *OUT_took_ownership = took_ownership;
-  }
-
-  // Ensure the SRK is available
-  TSS_RESULT result;
-  TSS_HKEY srk_handle;
-  TSS_UUID SRK_UUID = TSS_UUID_SRK;
-  if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(context_handle,
-                                                    TSS_PS_TYPE_SYSTEM,
-                                                    SRK_UUID,
-                                                    &srk_handle))) {
-  } else {
-    Tspi_Context_CloseObject(context_handle, srk_handle);
-  }
-
-  // If we can open the TPM with the default password, then we still need to
-  // zero the SRK password and unrestrict it, then change the owner password.
-  TSS_HTPM tpm_handle;
-  if (!platform_->FileExists(kTpmOwnedFile) &&
-      GetTpmWithAuth(context_handle, default_owner_password, &tpm_handle) &&
-      TestTpmAuth(tpm_handle)) {
-    if (!ZeroSrkPassword(context_handle, default_owner_password)) {
-      LOG(ERROR) << "Couldn't zero SRK password";
-      is_being_owned_ = false;
-      return false;
-    }
-
-    if (!UnrestrictSrk(context_handle, default_owner_password)) {
-      LOG(ERROR) << "Couldn't unrestrict the SRK";
-      is_being_owned_ = false;
-      return false;
-    }
-
-    SecureBlob owner_password;
-    CreateOwnerPassword(&owner_password);
-
-    tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
-                         TpmStatus::USES_RANDOM_OWNER |
-                         TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
-                         TpmStatus::ATTESTATION_NEEDS_OWNER);
-    if (!StoreOwnerPassword(owner_password, &tpm_status)) {
-      tpm_status.clear_owner_password();
-    }
-    StoreTpmStatus(tpm_status);
-
-    if ((result = ChangeOwnerPassword(context_handle, default_owner_password,
-                                      owner_password))) {
-      password_sync_lock_.Acquire();
-      owner_password_.assign(owner_password.begin(), owner_password.end());
-      password_sync_lock_.Release();
-    }
-    chromeos::Blob empty_blob(0);
-    platform_->WriteFile(kTpmOwnedFile, empty_blob);
-  } else {
-    // If we fall through here, then the TPM owned file doesn't exist, but we
-    // couldn't auth with the well-known password.  In this case, we must assume
-    // that the TPM has already been owned and set to a random password, so
-    // touch the TPM owned file.
-    if (!platform_->FileExists(kTpmOwnedFile)) {
-      chromeos::Blob empty_blob(0);
-      platform_->WriteFile(kTpmOwnedFile, empty_blob);
-    }
-  }
-
-  is_being_owned_ = false;
-  return true;
-}
-
 bool Tpm::GetRandomData(size_t length, chromeos::Blob* data) {
   ScopedTssContext context_handle;
   if ((*(context_handle.ptr()) = ConnectContext()) == 0) {
@@ -2008,116 +1282,43 @@
   return true;
 }
 
-void Tpm::ClearStoredOwnerPassword() {
-  TpmStatus tpm_status;
-  if (LoadTpmStatus(&tpm_status)) {
-    int32 dependency_flags = TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
-                             TpmStatus::ATTESTATION_NEEDS_OWNER;
-    if (tpm_status.flags() & dependency_flags) {
-      // The password is still needed, do not clear.
-      return;
-    }
-    if (tpm_status.has_owner_password()) {
-      tpm_status.clear_owner_password();
-      StoreTpmStatus(tpm_status);
-    }
-  }
-  password_sync_lock_.Acquire();
-  owner_password_.resize(0);
-  password_sync_lock_.Release();
-}
+bool Tpm::PerformEnabledOwnedCheck(bool* enabled, bool* owned) {
+  *enabled = false;
+  *owned = false;
 
-void Tpm::RemoveOwnerDependency(TpmOwnerDependency dependency) {
-  int32 flag_to_clear = TpmStatus::NONE;
-  switch (dependency) {
-    case kInstallAttributes:
-      flag_to_clear = TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER;
-      break;
-    case kAttestation:
-      flag_to_clear = TpmStatus::ATTESTATION_NEEDS_OWNER;
-      break;
-    default:
-      CHECK(false);
+  trousers::ScopedTssContext context(ConnectContext());
+  if (!context) {
+    return false;
   }
-  TpmStatus tpm_status;
-  if (!LoadTpmStatus(&tpm_status))
-    return;
-  tpm_status.set_flags(tpm_status.flags() & ~flag_to_clear);
-  StoreTpmStatus(tpm_status);
-}
 
-bool Tpm::LoadTpmStatus(TpmStatus* serialized) {
-  if (!platform_->FileExists(kTpmStatusFile)) {
+  TSS_HCONTEXT context_handle = context.context();
+  TSS_RESULT result;
+  TSS_HTPM tpm_handle;
+
+  if (TPM_ERROR(result = Tspi_Context_GetTpmObject(context_handle,
+                                                   &tpm_handle))) {
+    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_GetTpmObject";
     return false;
   }
-  SecureBlob file_data;
-  if (!platform_->ReadFile(kTpmStatusFile, &file_data)) {
-    return false;
+
+  UINT32 sub_cap = TSS_TPMCAP_PROP_OWNER;
+  UINT32 cap_length = 0;
+  trousers::ScopedTssMemory cap(context_handle);
+  if (TPM_ERROR(result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY,
+                                       sizeof(sub_cap),
+                                       reinterpret_cast<BYTE*>(&sub_cap),
+                                       &cap_length, cap.ptr())) == 0) {
+    if (cap_length >= (sizeof(TSS_BOOL))) {
+      *enabled = true;
+      *owned = ((*(reinterpret_cast<TSS_BOOL*>(cap.value()))) != 0);
+    }
+  } else if (ERROR_CODE(result) == TPM_E_DISABLED) {
+    *enabled = false;
   }
-  if (!serialized->ParseFromArray(
-           static_cast<const unsigned char*>(file_data.data()),
-           file_data.size())) {
-    return false;
-  }
+
   return true;
 }
 
-bool Tpm::StoreTpmStatus(const TpmStatus& serialized) {
-  int old_mask = platform_->SetMask(kDefaultUmask);
-  if (platform_->FileExists(kTpmStatusFile)) {
-    do {
-      int64 file_size;
-      if (!platform_->GetFileSize(kTpmStatusFile, &file_size)) {
-        break;
-      }
-      SecureBlob random;
-      if (!GetRandomData(file_size, &random)) {
-        break;
-      }
-      FILE* file = platform_->OpenFile(kTpmStatusFile, "wb+");
-      if (!file) {
-        break;
-      }
-      if (!platform_->WriteOpenFile(file, random)) {
-        platform_->CloseFile(file);
-        break;
-      }
-      platform_->CloseFile(file);
-    } while (false);
-    platform_->DeleteFile(kTpmStatusFile, false);
-  }
-  SecureBlob final_blob(serialized.ByteSize());
-  serialized.SerializeWithCachedSizesToArray(
-      static_cast<google::protobuf::uint8*>(final_blob.data()));
-  bool ok = platform_->WriteFile(kTpmStatusFile, final_blob);
-  platform_->SetMask(old_mask);
-  return ok;
-}
-
-base::Value* Tpm::GetStatusValue(TpmInit* init) {
-  base::DictionaryValue* dv = new base::DictionaryValue();
-  TpmStatusInfo status;
-  GetStatus(true, &status);
-
-  dv->SetBoolean("can_connect", status.CanConnect);
-  dv->SetBoolean("can_load_srk", status.CanLoadSrk);
-  dv->SetBoolean("can_load_srk_pubkey", status.CanLoadSrkPublicKey);
-  dv->SetBoolean("has_cryptohome_key", status.HasCryptohomeKey);
-  dv->SetBoolean("can_encrypt", status.CanEncrypt);
-  dv->SetBoolean("can_decrypt", status.CanDecrypt);
-  dv->SetBoolean("has_context", status.ThisInstanceHasContext);
-  dv->SetBoolean("has_key_handle", status.ThisInstanceHasKeyHandle);
-  dv->SetInteger("last_error", status.LastTpmError);
-
-  if (init) {
-    dv->SetBoolean("enabled", init->IsTpmEnabled());
-    dv->SetBoolean("owned", init->IsTpmOwned());
-    dv->SetBoolean("being_owned", init->IsTpmBeingOwned());
-  }
-
-  return dv;
-}
-
 bool Tpm::GetEndorsementPublicKey(SecureBlob* ek_public_key) {
   // Connect to the TPM as the owner.
   ScopedTssContext context_handle;
@@ -3363,7 +2564,7 @@
                            TSS_HOBJECT object,
                            TSS_FLAG flag,
                            TSS_FLAG sub_flag,
-                           SecureBlob* data) {
+                           SecureBlob* data) const {
   UINT32 length = 0;
   ScopedTssMemory buf(context);
   TSS_RESULT result = Tspi_GetAttribData(object, flag, sub_flag, &length,
@@ -3378,4 +2579,215 @@
   return true;
 }
 
+void Tpm::SetOwnerPassword(const chromeos::SecureBlob& owner_password) {
+  base::AutoLock lock(password_sync_lock_);
+  owner_password_.assign(owner_password.begin(), owner_password.end());
+}
+
+bool Tpm::CreateWrappedRsaKey(TSS_HCONTEXT context_handle,
+                              SecureBlob* wrapped_key) {
+  TSS_RESULT result;
+
+  // Load the Storage Root Key
+  trousers::ScopedTssKey srk_handle(context_handle);
+  if (!LoadSrk(context_handle, srk_handle.ptr(), &result)) {
+    if (result != kKeyNotFoundError) {
+      TPM_LOG(INFO, result) << "CreateWrappedRsaKey: Cannot load SRK";
+    }
+    return false;
+  }
+
+  // Make sure we can get the public key for the SRK.  If not, then the TPM
+  // is not available.
+  unsigned int size_n;
+  trousers::ScopedTssMemory public_srk(context_handle);
+  if (TPM_ERROR(result = Tspi_Key_GetPubKey(srk_handle, &size_n,
+                                            public_srk.ptr()))) {
+    TPM_LOG(INFO, result) << "CreateWrappedRsaKey: Cannot load SRK pub key";
+    return false;
+  }
+
+  // Create the key object
+  TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_VOLATILE | \
+                        TSS_KEY_MIGRATABLE | kDefaultTpmRsaKeyFlag;
+  trousers::ScopedTssKey local_key_handle(context_handle);
+  if (TPM_ERROR(result = Tspi_Context_CreateObject(context_handle,
+                                                   TSS_OBJECT_TYPE_RSAKEY,
+                                                   init_flags,
+                                                   local_key_handle.ptr()))) {
+    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
+    return false;
+  }
+
+  // Set the attributes
+  UINT32 sig_scheme = TSS_SS_RSASSAPKCS1V15_DER;
+  if (TPM_ERROR(result = Tspi_SetAttribUint32(local_key_handle,
+                                              TSS_TSPATTRIB_KEY_INFO,
+                                              TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
+                                              sig_scheme))) {
+    TPM_LOG(ERROR, result) << "Error calling Tspi_SetAttribUint32";
+    return false;
+  }
+
+  UINT32 enc_scheme = TSS_ES_RSAESPKCSV15;
+  if (TPM_ERROR(result = Tspi_SetAttribUint32(local_key_handle,
+                                              TSS_TSPATTRIB_KEY_INFO,
+                                              TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
+                                              enc_scheme))) {
+    TPM_LOG(ERROR, result) << "Error calling Tspi_SetAttribUint32";
+    return false;
+  }
+
+  trousers::ScopedTssPolicy policy_handle(context_handle);
+  if (TPM_ERROR(result = Tspi_Context_CreateObject(context_handle,
+                                                   TSS_OBJECT_TYPE_POLICY,
+                                                   TSS_POLICY_MIGRATION,
+                                                   policy_handle.ptr()))) {
+    TPM_LOG(ERROR, result) << "Error creating policy object";
+    return false;
+  }
+
+  // Set a random migration policy password, and discard it.  The key will not
+  // be migrated, but to create the key outside of the TPM, we have to do it
+  // this way.
+  SecureBlob migration_password(kDefaultDiscardableWrapPasswordLength);
+  CryptoLib::GetSecureRandom(
+      static_cast<unsigned char*>(migration_password.data()),
+      migration_password.size());
+  if (TPM_ERROR(result = Tspi_Policy_SetSecret(policy_handle,
+                         TSS_SECRET_MODE_PLAIN,
+                         migration_password.size(),
+                         static_cast<BYTE*>(migration_password.data())))) {
+    TPM_LOG(ERROR, result) << "Error setting migration policy password";
+    return false;
+  }
+
+  if (TPM_ERROR(result = Tspi_Policy_AssignToObject(policy_handle,
+                                                    local_key_handle))) {
+    TPM_LOG(ERROR, result) << "Error assigning migration policy";
+    return false;
+  }
+
+  SecureBlob n;
+  SecureBlob p;
+  if (!CryptoLib::CreateRsaKey(kDefaultTpmRsaKeyBits, &n, &p)) {
+    LOG(ERROR) << "Error creating RSA key";
+    return false;
+  }
+
+  if (TPM_ERROR(result = Tspi_SetAttribData(local_key_handle,
+                                            TSS_TSPATTRIB_RSAKEY_INFO,
+                                            TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
+                                            n.size(),
+                                            static_cast<BYTE *>(n.data())))) {
+    TPM_LOG(ERROR, result) << "Error setting RSA modulus";
+    return false;
+  }
+
+  if (TPM_ERROR(result = Tspi_SetAttribData(local_key_handle,
+                                            TSS_TSPATTRIB_KEY_BLOB,
+                                            TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY,
+                                            p.size(),
+                                            static_cast<BYTE *>(p.data())))) {
+    TPM_LOG(ERROR, result) << "Error setting private key";
+    return false;
+  }
+
+  if (TPM_ERROR(result = Tspi_Key_WrapKey(local_key_handle,
+                                          srk_handle,
+                                          0))) {
+    TPM_LOG(ERROR, result) << "Error wrapping RSA key";
+    return false;
+  }
+
+  if (!GetKeyBlob(context_handle, local_key_handle, wrapped_key, &result)) {
+    return false;
+  }
+
+  return true;
+}
+
+bool Tpm::GetKeyBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
+                     SecureBlob* data_out, TSS_RESULT* result) const {
+  *result = TSS_SUCCESS;
+
+  if (!GetDataAttribute(context_handle, key_handle, TSS_TSPATTRIB_KEY_BLOB,
+      TSS_TSPATTRIB_KEYBLOB_BLOB, data_out)) {
+    LOG(ERROR) << __func__ << ": Failed to get key blob.";
+    return false;
+  }
+
+  return true;
+}
+
+bool Tpm::LoadWrappedKey(TSS_HCONTEXT context_handle,
+                         const chromeos::SecureBlob& wrapped_key,
+                         TSS_HKEY* key_handle,
+                         TSS_RESULT* result) const {
+  // Load the Storage Root Key
+  trousers::ScopedTssKey srk_handle(context_handle);
+  if (!LoadSrk(context_handle, srk_handle.ptr(), result)) {
+    if (*result != kKeyNotFoundError) {
+      TPM_LOG(INFO, *result) << "LoadWrappedKey: Cannot load SRK";
+    }
+    return false;
+  }
+
+  // Make sure we can get the public key for the SRK.  If not, then the TPM
+  // is not available.
+  {
+    SecureBlob pubkey;
+    if (!GetPublicKeyBlob(context_handle, srk_handle, &pubkey, result)) {
+      TPM_LOG(INFO, *result) << "LoadWrappedKey: Cannot load SRK public key";
+      return false;
+    }
+  }
+
+  if (TPM_ERROR(*result = Tspi_Context_LoadKeyByBlob(
+                                  context_handle,
+                                  srk_handle,
+                                  wrapped_key.size(),
+                                  const_cast<BYTE*>(static_cast<const BYTE*>(
+                                    wrapped_key.const_data())),
+                                  key_handle))) {
+    TPM_LOG(INFO, *result) << "LoadWrappedKey: Cannot load key " \
+                           << "from blob";
+    return false;
+  }
+
+  SecureBlob pub_key;
+  // Make sure that we can get the public key
+  if (!GetPublicKeyBlob(context_handle, *key_handle, &pub_key, result)) {
+    Tspi_Context_CloseObject(context_handle, *key_handle);
+    return false;
+  }
+
+  return true;
+}
+
+bool Tpm::LoadKeyByUuid(TSS_HCONTEXT context_handle,
+                        TSS_UUID key_uuid,
+                        TSS_HKEY* key_handle,
+                        chromeos::SecureBlob* key_blob,
+                        TSS_RESULT* result) const {
+  if (TPM_ERROR(*result = Tspi_Context_LoadKeyByUUID(context_handle,
+                                                     TSS_PS_TYPE_SYSTEM,
+                                                     key_uuid,
+                                                     key_handle))) {
+    TPM_LOG(INFO, *result) << "LoadKeyByUuid: failed LoadKeyByUUID";
+    return false;
+  }
+
+  if (key_blob && !GetKeyBlob(context_handle, *key_handle, key_blob, result)) {
+    Tspi_Context_CloseObject(context_handle, *key_handle);
+    return false;
+  }
+
+  return true;
+}
+
+void Tpm::CloseContext(TSS_HCONTEXT context) const {
+  Tspi_Context_Close(context);
+}
+
 }  // namespace cryptohome
diff --git a/tpm.h b/tpm.h
index e0ab80a..981db4d 100644
--- a/tpm.h
+++ b/tpm.h
@@ -12,7 +12,6 @@
 #include <base/logging.h>
 #include <base/memory/scoped_ptr.h>
 #include <base/synchronization/lock.h>
-#include <base/values.h>
 #include <chromeos/secure_blob.h>
 #include <chromeos/utility.h>
 #include <metrics/metrics_library.h>
@@ -20,7 +19,6 @@
 #include <trousers/tss.h>
 #include <trousers/trousers.h>
 
-#include "platform.h"
 #include "tpm_status.pb.h"
 
 #ifndef CRYPTOHOME_TPM_H_
@@ -28,10 +26,6 @@
 
 namespace cryptohome {
 
-class TpmInit;
-
-extern const TSS_UUID kCryptohomeWellKnownUuid;
-
 class Tpm {
  public:
   enum TpmRetryAction {
@@ -42,11 +36,6 @@
     RetryReboot
   };
 
-  enum TpmOwnerDependency {
-    kInstallAttributes,
-    kAttestation
-  };
-
   struct TpmStatusInfo {
     TSS_RESULT LastTpmError;
     bool CanConnect;
@@ -63,53 +52,42 @@
 
   virtual ~Tpm();
 
-  // Initializes the Tpm instance
+  // Encrypts a data blob using the provided RSA key
   //
   // Parameters
-  //   crypto - The Crypto instance to use (for generating an RSA key, entropy,
-  //            etc.)
-  //   open_key - Whether or not to open (load) the cryptohome TPM key
-  virtual bool Init(Platform* platform, bool open_key);
-
-  // Tries to connect to the TPM
-  virtual bool Connect(TpmRetryAction* retry_action);
-
-  // Returns true if this instance is connected to the TPM
-  virtual bool IsConnected();
-
-  // Disconnects from the TPM
-  virtual void Disconnect();
-
-  // Encrypts a data blob using the TPM cryptohome RSA key
-  //
-  // Parameters
+  //   context_handle - The TPM context
+  //   key_handle - The loaded TPM key handle
   //   plaintext - One RSA message to encrypt
   //   key - AES key to encrypt with
-  //   ciphertext
-  virtual bool Encrypt(const chromeos::SecureBlob& plaintext,
-                       const chromeos::SecureBlob& key,
-                       chromeos::SecureBlob* ciphertext,
-                       TpmRetryAction* retry_action);
+  //   ciphertext (OUT) - Encrypted blob
+  //   result (OUT) - TPM error code
+  virtual bool EncryptBlob(TSS_HCONTEXT context_handle,
+                           TSS_HKEY key_handle,
+                           const chromeos::SecureBlob& plaintext,
+                           const chromeos::SecureBlob& key,
+                           chromeos::SecureBlob* ciphertext,
+                           TSS_RESULT* result);
 
-  // Decrypts a data blob using the TPM cryptohome RSA key
+  // Decrypts a data blob using the provided RSA key
   //
   // Parameters
-  //   ciphertext - One RSA message to decrypt
-  //   key - AES key to decrypt with
-  //   plaintext
-  virtual bool Decrypt(const chromeos::SecureBlob& ciphertext,
-                       const chromeos::SecureBlob& key,
-                       chromeos::SecureBlob* plaintext,
-                       TpmRetryAction* retry_action);
+  //   context_handle - The TPM context
+  //   key_handle - The loaded TPM key handle
+  //   ciphertext - One RSA message to encrypt
+  //   key - AES key to encrypt with
+  //   plaintext (OUT) - Decrypted blob
+  //   result (OUT) - TPM error code
+  virtual bool DecryptBlob(TSS_HCONTEXT context_handle,
+                           TSS_HKEY key_handle,
+                           const chromeos::SecureBlob& ciphertext,
+                           const chromeos::SecureBlob& key,
+                           chromeos::SecureBlob* plaintext,
+                           TSS_RESULT* result);
 
-  // Retrieves the sha1sum of the public key component of the cryptohome RSA key
-  virtual TpmRetryAction GetPublicKeyHash(chromeos::SecureBlob* hash);
-
-  // Gets the TPM status information as a Value.
-  //
-  // Parameters
-  //   init - If non-NULL, overrides some of the status values
-  base::Value* GetStatusValue(TpmInit* init);
+  // Retrieves the sha1sum of the public key component of the RSA key
+  virtual TpmRetryAction GetPublicKeyHash(TSS_HCONTEXT context_handle,
+                                          TSS_HKEY key_handle,
+                                          chromeos::SecureBlob* hash);
 
   // Returns the owner password if this instance was used to take ownership.
   // This will only occur when the TPM is unowned, which will be on OOBE
@@ -118,25 +96,40 @@
   //   owner_password (OUT) - The random owner password used
   virtual bool GetOwnerPassword(chromeos::Blob* owner_password);
 
-  // Clears the owner password from storage if no dependencies exist.
-  void ClearStoredOwnerPassword();
-
-  // Removes the given owner dependency. When all dependencies have been removed
-  // the owner password can be cleared.
-  virtual void RemoveOwnerDependency(TpmOwnerDependency dependency);
 
   // Returns whether or not the TPM is enabled.  This method call returns a
   // cached result because querying the TPM directly will block if ownership is
   // currently being taken (such as on a separate thread).
   virtual bool IsEnabled() const { return !is_disabled_; }
+  virtual void SetIsEnabled(bool enabled) { is_disabled_ = !enabled; }
 
   // Returns whether or not the TPM is owned.  This method call returns a cached
   // result because querying the TPM directly will block if ownership is
   // currently being taken (such as on a separate thread).
   virtual bool IsOwned() const { return is_owned_; }
+  virtual void SetIsOwned(bool owned) { is_owned_ = owned; }
+
+  // Returns whether or not the TPM is enabled and owned using a call to
+  // Tspi_TPM_GetCapability.
+  //
+  // Unlike former functions, this function performs the check (which could take
+  // some time) every time it is invoked. It does not use cached value.
+  //
+  // Parameters
+  //   enabled (OUT) - Whether the TPM is enabled
+  //   owned (OUT) - Whether the TPM is owned
+  //
+  // Returns true if the check was successfully carried out.
+  bool PerformEnabledOwnedCheck(bool* enabled, bool* owned);
+
+  // Returns whether or not this instance has been setup'd by an external
+  // entity (such as cryptohome::TpmInit).
+  virtual bool IsInitialized() const { return initialized_; }
+  virtual void SetIsInitialized(bool done) { initialized_ = done; }
 
   // Returns whether or not the TPM is being owned
   virtual bool IsBeingOwned() const { return is_being_owned_; }
+  virtual void SetIsBeingOwned(bool value) { is_being_owned_ = value; }
 
   // Runs the TPM initialization sequence.  This may take a long time due to the
   // call to Tspi_TPM_TakeOwnership.
@@ -397,148 +390,14 @@
   // Extends the PCR given by |pcr_index| using a SHA-1 hash of |extension|.
   virtual bool ExtendPCR(int pcr_index, const chromeos::SecureBlob& extension);
 
- protected:
-  // Default constructor
-  Tpm();
-
- private:
-  // Gets the TPM status information
-  //
-  // Parameters
-  //   check_crypto - Whether to check if encrypt/decrypt works (may take
-  //                  longer)
-  //   status (OUT) - The TpmStatusInfo structure containing the results
-  void GetStatus(bool check_crypto, Tpm::TpmStatusInfo* status);
-
-  bool IsTransient(TSS_RESULT result);
-
-  TpmRetryAction HandleError(TSS_RESULT result);
-
-  bool SaveCryptohomeKey(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                         TSS_RESULT* result);
-
   bool OpenAndConnectTpm(TSS_HCONTEXT* context_handle, TSS_RESULT* result);
 
-  // Populates |context_handle| with a valid TSS_HCONTEXT and |tpm_handle| with
-  // its matching TPM object iff the owner password is available and
-  // authorization is successfully acquired.
-  bool ConnectContextAsOwner(TSS_HCONTEXT* context_handle,
-                             TSS_HTPM* tpm_handle);
-
-  // Populates |context_handle| with a valid TSS_HCONTEXT and |tpm_handle| with
-  // its matching TPM object authorized by the given delegation.
-  bool ConnectContextAsDelegate(const chromeos::SecureBlob& delegate_blob,
-                                const chromeos::SecureBlob& delegate_secret,
-                                TSS_HCONTEXT* context, TSS_HTPM* tpm);
-
-  // Populates |context_handle| with a valid TSS_HCONTEXT and |tpm_handle| with
-  // its matching TPM object iff the context can be created and a TPM object
-  // exists in the TSS.
-  bool ConnectContextAsUser(TSS_HCONTEXT* context_handle,
-                            TSS_HTPM* tpm_handle);
-
-  bool CreateCryptohomeKey(TSS_HCONTEXT context_handle,
-                           bool create_in_tpm, TSS_RESULT* result);
-
-  bool LoadCryptohomeKey(TSS_HCONTEXT context_handle, TSS_HKEY* key_handle,
-                         TSS_RESULT* result);
-
-  bool LoadOrCreateCryptohomeKey(TSS_HCONTEXT context_handle,
-                                 bool create_in_tpm,
-                                 TSS_HKEY* key_handle,
-                                 TSS_RESULT* result);
-
-  bool EncryptBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                   const chromeos::SecureBlob& plaintext,
-                   const chromeos::SecureBlob& key,
-                   chromeos::SecureBlob* ciphertext, TSS_RESULT* result);
-
-  bool DecryptBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                   const chromeos::SecureBlob& ciphertext,
-                   const chromeos::SecureBlob& key,
-                   chromeos::SecureBlob* plaintext, TSS_RESULT* result);
-
-  bool GetKeyBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                  chromeos::SecureBlob* data_out, TSS_RESULT* result);
-
-  bool GetPublicKeyBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
-                        chromeos::SecureBlob* data_out, TSS_RESULT* result);
-
   // Tries to connect to the TPM
   virtual TSS_HCONTEXT ConnectContext();
 
-  // Disconnects from the TPM
-  virtual void DisconnectContext(TSS_HCONTEXT context_handle);
-
-  // Gets a handle to the SRK
-  bool LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle,
-               TSS_RESULT* result);
-
-  // Stores the TPM owner password to the TpmStatus object
-  bool StoreOwnerPassword(const chromeos::Blob& owner_password,
-                          TpmStatus* tpm_status);
-
-  // Retrieves the TPM owner password
-  bool LoadOwnerPassword(const TpmStatus& tpm_status,
-                         chromeos::Blob* owner_password);
-
-  // Loads the TpmStatus object
-  bool LoadTpmStatus(TpmStatus* serialized);
-
-  // Saves the TpmStatus object
-  bool StoreTpmStatus(const TpmStatus& serialized);
-
-  // Returns the size of the specified NVRAM space.
-  //
-  // Parameters
-  //   context_handle - The context handle for the TPM session
-  //   index - NVRAM Space index
-  // Returns -1 if the index, handle, or space is invalid.
-  unsigned int GetNvramSizeForContext(TSS_HCONTEXT context_handle,
-                                      TSS_HTPM tpm_handle,
-                                      uint32_t index);
-
-  // Returns if an Nvram space exists using the given context.
-  bool IsNvramDefinedForContext(TSS_HCONTEXT context_handle,
-                                TSS_HTPM tpm_handle,
-                                uint32_t index);
-
-  // Returns if bWriteDefine is true for a given NVRAM space using the given
-  // context.
-  bool IsNvramLockedForContext(TSS_HCONTEXT context_handle,
-                               TSS_HTPM tpm_handle,
-                               uint32_t index);
-
-  // Reads an NVRAM space using the given context.
-  bool ReadNvramForContext(TSS_HCONTEXT context_handle,
-                           TSS_HTPM tpm_handle,
-                           TSS_HPOLICY policy_handle,
-                           uint32_t index,
-                           chromeos::SecureBlob* blob);
-
-  // Returns whether or not the TPM is disabled by checking a flag in the TPM's
-  // entry in /sys/class/misc
-  bool IsDisabledCheckViaSysfs();
-
-  // Returns whether or not the TPM is owned by checking a flag in the TPM's
-  // entry in /sys/class/misc
-  bool IsOwnedCheckViaSysfs();
-
-  // Returns whether or not the TPM is enabled and owned using a call to
-  // Tspi_TPM_GetCapability
-  //
-  // Parameters
-  //   context_handle - The context handle for the TPM session
-  //   enabled (OUT) - Whether the TPM is enabled
-  //   owned (OUT) - Whether the TPM is owned
-  void IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle,
-                                     bool* enabled, bool* owned);
-
-  // Attempts to create the endorsement key in the TPM
-  //
-  // Parameters
-  //   context_handle - The context handle for the TPM session
-  bool CreateEndorsementKey(TSS_HCONTEXT context_handle);
+  // Frees up the context. This is different from Disconnect() method. This
+  // version does not touch on resources owned by this TPM instance.
+  virtual void CloseContext(TSS_HCONTEXT context_handle) const;
 
   // Checks to see if the endorsement key is available by attempting to get its
   // public key
@@ -547,11 +406,11 @@
   //   context_handle - The context handle for the TPM session
   bool IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle);
 
-  // Creates a random owner password
+  // Attempts to create the endorsement key in the TPM
   //
   // Parameters
-  //   password (OUT) - the generated password
-  void CreateOwnerPassword(chromeos::SecureBlob* password);
+  //   context_handle - The context handle for the TPM session
+  bool CreateEndorsementKey(TSS_HCONTEXT context_handle);
 
   // Attempts to take ownership of the TPM
   //
@@ -588,13 +447,6 @@
                            const chromeos::SecureBlob& previous_owner_password,
                            const chromeos::SecureBlob& owner_password);
 
-  // Gets a handle to the TPM from the specified context
-  //
-  // Parameters
-  //   context_handle - The context handle for the TPM session
-  //   tpm_handle (OUT) - The handle for the TPM on success
-  bool GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle);
-
   // Gets a handle to the TPM from the specified context with the given owner
   // password
   //
@@ -606,6 +458,137 @@
                       const chromeos::SecureBlob& owner_password,
                       TSS_HTPM* tpm_handle);
 
+  // Test the TPM auth by calling Tspi_TPM_GetStatus
+  //
+  // Parameters
+  //   tpm_handle = The TPM handle
+  bool TestTpmAuth(TSS_HTPM tpm_handle);
+
+  // Sets the TPM owner password to be used in subsequent commands
+  //
+  // Parameters
+  //   owner_password - The owner password for the TPM
+  void SetOwnerPassword(const chromeos::SecureBlob& owner_password);
+
+  // Gets a handle to the SRK
+  bool LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle,
+               TSS_RESULT* result) const;
+
+  bool IsTransient(TSS_RESULT result);
+
+  bool GetPublicKeyBlob(TSS_HCONTEXT context_handle,
+                        TSS_HKEY key_handle,
+                        chromeos::SecureBlob* data_out,
+                        TSS_RESULT* result) const;
+
+  bool GetKeyBlob(TSS_HCONTEXT context_handle, TSS_HKEY key_handle,
+                  chromeos::SecureBlob* data_out, TSS_RESULT* result) const;
+
+  // Creates an RSA key wrapped by the TPM's Storage Root Key. The key is
+  // created by OpenSSL, and not by the TPM.
+  //
+  // Parameters
+  //   context_handle - The context handle for the TPM session
+  //   wrapped_key (OUT) - A blob representing the wrapped key
+  bool CreateWrappedRsaKey(TSS_HCONTEXT context_handle,
+                           chromeos::SecureBlob* wrapped_key);
+
+  // Loads an SRK-wrapped key into the TPM.
+  //
+  // Parameters
+  //   context_handle - The context handle for the TPM session.
+  //   wrapped_key - The blob (as produced by CreateWrappedRsaKey).
+  //   key_handle (OUT) - A handle to the key loaded into the TPM.
+  bool LoadWrappedKey(TSS_HCONTEXT context_handle,
+                      const chromeos::SecureBlob& wrapped_key,
+                      TSS_HKEY* key_handle,
+                      TSS_RESULT* result) const;
+
+  // Loads a key by well-known UUID.
+  //
+  // Parameters
+  //   context_handle - The context handle for the TPM session.
+  //   key_uuid - The well-known UUID identifying the TPM key.
+  //   key_handle (OUT) - A handle to the key loaded into the TPM.
+  //   key_blob (OUT) - If non-null, the blob representing this loaded key.
+  bool LoadKeyByUuid(TSS_HCONTEXT context_handle,
+                     TSS_UUID key_uuid,
+                     TSS_HKEY* key_handle,
+                     chromeos::SecureBlob* key_blob,
+                     TSS_RESULT* result) const;
+
+  TpmRetryAction HandleError(TSS_RESULT result);
+
+  // Gets the TPM status information. If there |context| and |key| are supplied,
+  // they will be used in encryption/decryption test. They can be 0 to bypass
+  // the test.
+  //
+  // Parameters
+  //   context - The TPM context to check for encryption/decryption
+  //   key - The key to check for encryption/decryption
+  //   status (OUT) - The TpmStatusInfo structure containing the results
+  void GetStatus(TSS_HCONTEXT context,
+                 TSS_HKEY key,
+                 Tpm::TpmStatusInfo* status);
+
+ protected:
+  // Default constructor
+  Tpm();
+
+ private:
+  // Populates |context_handle| with a valid TSS_HCONTEXT and |tpm_handle| with
+  // its matching TPM object iff the owner password is available and
+  // authorization is successfully acquired.
+  bool ConnectContextAsOwner(TSS_HCONTEXT* context_handle,
+                             TSS_HTPM* tpm_handle);
+
+  // Populates |context_handle| with a valid TSS_HCONTEXT and |tpm_handle| with
+  // its matching TPM object authorized by the given delegation.
+  bool ConnectContextAsDelegate(const chromeos::SecureBlob& delegate_blob,
+                                const chromeos::SecureBlob& delegate_secret,
+                                TSS_HCONTEXT* context, TSS_HTPM* tpm);
+
+  // Populates |context_handle| with a valid TSS_HCONTEXT and |tpm_handle| with
+  // its matching TPM object iff the context can be created and a TPM object
+  // exists in the TSS.
+  bool ConnectContextAsUser(TSS_HCONTEXT* context_handle,
+                            TSS_HTPM* tpm_handle);
+
+  // Returns the size of the specified NVRAM space.
+  //
+  // Parameters
+  //   context_handle - The context handle for the TPM session
+  //   index - NVRAM Space index
+  // Returns -1 if the index, handle, or space is invalid.
+  unsigned int GetNvramSizeForContext(TSS_HCONTEXT context_handle,
+                                      TSS_HTPM tpm_handle,
+                                      uint32_t index);
+
+  // Returns if an Nvram space exists using the given context.
+  bool IsNvramDefinedForContext(TSS_HCONTEXT context_handle,
+                                TSS_HTPM tpm_handle,
+                                uint32_t index);
+
+  // Returns if bWriteDefine is true for a given NVRAM space using the given
+  // context.
+  bool IsNvramLockedForContext(TSS_HCONTEXT context_handle,
+                               TSS_HTPM tpm_handle,
+                               uint32_t index);
+
+  // Reads an NVRAM space using the given context.
+  bool ReadNvramForContext(TSS_HCONTEXT context_handle,
+                           TSS_HTPM tpm_handle,
+                           TSS_HPOLICY policy_handle,
+                           uint32_t index,
+                           chromeos::SecureBlob* blob);
+
+  // Gets a handle to the TPM from the specified context
+  //
+  // Parameters
+  //   context_handle - The context handle for the TPM session
+  //   tpm_handle (OUT) - The handle for the TPM on success
+  bool GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle);
+
   // Gets a handle to the TPM from the specified context with the given
   // delegation.
   //
@@ -619,12 +602,6 @@
                             const chromeos::SecureBlob& delegate_secret,
                             TSS_HTPM* tpm_handle);
 
-  // Test the TPM auth by calling Tspi_TPM_GetStatus
-  //
-  // Parameters
-  //   tpm_handle = The TPM handle
-  bool TestTpmAuth(TSS_HTPM tpm_handle);
-
   // Decrypts and parses an identity request.
   //
   // Parameters
@@ -675,13 +652,11 @@
                         TSS_HOBJECT object,
                         TSS_FLAG flag,
                         TSS_FLAG sub_flag,
-                        chromeos::SecureBlob* data);
+                        chromeos::SecureBlob* data) const;
 
   // Member variables
   bool initialized_;
   chromeos::SecureBlob srk_auth_;
-  TSS_HCONTEXT context_handle_;
-  TSS_HKEY key_handle_;
 
   // If TPM ownership is taken, owner_password_ contains the password used
   chromeos::SecureBlob owner_password_;
@@ -702,7 +677,6 @@
   static Tpm* singleton_;
   static base::Lock singleton_lock_;
 
-  Platform* platform_;
   scoped_ptr<MetricsLibraryInterface> metrics_;
 
   DISALLOW_COPY_AND_ASSIGN(Tpm);
diff --git a/tpm_init.cc b/tpm_init.cc
index 7cd03f4..ff830f3 100644
--- a/tpm_init.cc
+++ b/tpm_init.cc
@@ -9,22 +9,41 @@
 #include <base/logging.h>
 #include <base/threading/platform_thread.h>
 #include <base/time/time.h>
+#include <trousers/scoped_tss_type.h>
 
 #include "attestation.h"
+#include "cryptolib.h"
+#include "interface.h"
 
 using base::PlatformThread;
 using base::PlatformThreadHandle;
+using chromeos::SecureBlob;
 
 namespace cryptohome {
 
+const int kMaxTimeoutRetries = 5;
+
+const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled";
+const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned";
+const char* kTpmOwnedFileOld = "/var/lib/.tpm_owned";
+const char* kTpmStatusFileOld = "/var/lib/.tpm_status";
+const char* kTpmOwnedFile = "/mnt/stateful_partition/.tpm_owned";
+const char* kTpmStatusFile = "/mnt/stateful_partition/.tpm_status";
+const char* kOpenCryptokiPath = "/var/lib/opencryptoki";
+const char kDefaultCryptohomeKeyFile[] = "/home/.shadow/cryptohome.key";
+
+const int kOwnerPasswordLength = 12;
+const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET;
+const TSS_UUID kCryptohomeWellKnownUuid = {0x0203040b, 0, 0, 0, 0,
+                                           {0, 9, 8, 1, 0, 3}};
+
 // TpmInitTask is a private class used to handle asynchronous initialization of
 // the TPM.
 class TpmInitTask : public PlatformThread::Delegate {
  public:
-  explicit TpmInitTask(Platform* platform)
+  explicit TpmInitTask()
         : tpm_(NULL),
-        init_(NULL),
-        platform_(platform) {
+        init_(NULL) {
   }
 
   virtual ~TpmInitTask() {
@@ -32,8 +51,9 @@
 
   void Init(TpmInit* init) {
     init_ = init;
-    if (tpm_)
-      tpm_->Init(platform_, false);
+    if (tpm_) {
+      init->SetupTpm(false);
+    }
   }
 
   virtual void ThreadMain() {
@@ -53,16 +73,18 @@
  private:
   Tpm* tpm_;
   TpmInit* init_;
-  Platform* platform_;
 };
 
-TpmInit::TpmInit(Platform* platform)
-    : tpm_init_task_(new TpmInitTask(platform)),
+TpmInit::TpmInit(Tpm* tpm, Platform* platform)
+    : tpm_init_task_(new TpmInitTask()),
       notify_callback_(NULL),
       initialize_called_(false),
       initialize_took_ownership_(false),
       initialization_time_(0),
-      platform_(platform) {
+      platform_(platform),
+      cryptohome_context_(0),
+      cryptohome_key_(0, 0) {
+  set_tpm(tpm);
 }
 
 TpmInit::~TpmInit() {
@@ -90,11 +112,7 @@
   tpm_init_task_->Init(this);
 }
 
-bool TpmInit::GetRandomData(int length, chromeos::Blob* data) {
-  return tpm_init_task_->get_tpm()->GetRandomData(length, data);
-}
-
-bool TpmInit::StartInitializeTpm() {
+bool TpmInit::AsyncInitializeTpm() {
   initialize_called_ = true;
   if (!PlatformThread::Create(0, tpm_init_task_.get(), &init_thread_)) {
     LOG(ERROR) << "Unable to create TPM initialization background thread.";
@@ -118,10 +136,18 @@
   return tpm_init_task_->get_tpm()->IsOwned();
 }
 
+void TpmInit::SetTpmOwned(bool owned) {
+  tpm_init_task_->get_tpm()->SetIsOwned(owned);
+}
+
 bool TpmInit::IsTpmBeingOwned() {
   return tpm_init_task_->get_tpm()->IsBeingOwned();
 }
 
+void TpmInit::SetTpmBeingOwned(bool being_owned) {
+  tpm_init_task_->get_tpm()->SetIsBeingOwned(being_owned);
+}
+
 bool TpmInit::HasInitializeBeenCalled() {
   return initialize_called_;
 }
@@ -131,12 +157,26 @@
 }
 
 void TpmInit::ClearStoredTpmPassword() {
-  tpm_init_task_->get_tpm()->ClearStoredOwnerPassword();
+  TpmStatus tpm_status;
+  if (LoadTpmStatus(&tpm_status)) {
+    int32 dependency_flags = TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
+                             TpmStatus::ATTESTATION_NEEDS_OWNER;
+    if (tpm_status.flags() & dependency_flags) {
+      // The password is still needed, do not clear.
+      return;
+    }
+    if (tpm_status.has_owner_password()) {
+      tpm_status.clear_owner_password();
+      StoreTpmStatus(tpm_status);
+    }
+  }
+  SecureBlob empty;
+  get_tpm()->SetOwnerPassword(empty);
 }
 
 void TpmInit::ThreadMain() {
   base::TimeTicks start = base::TimeTicks::Now();
-  bool initialize_result = tpm_init_task_->get_tpm()->InitializeTpm(
+  bool initialize_result = InitializeTpm(
       &initialize_took_ownership_);
   base::TimeDelta delta = (base::TimeTicks::Now() - start);
   initialization_time_ = delta.InMilliseconds();
@@ -149,4 +189,455 @@
   }
 }
 
+void TpmInit::MigrateStatusFiles() {
+  if (!platform_->FileExists(kTpmOwnedFile) &&
+      platform_->FileExists(kTpmOwnedFileOld)) {
+    platform_->Move(kTpmOwnedFileOld, kTpmOwnedFile);
+  }
+  if (!platform_->FileExists(kTpmStatusFile) &&
+      platform_->FileExists(kTpmStatusFileOld)) {
+    platform_->Move(kTpmStatusFileOld, kTpmStatusFile);
+  }
+}
+
+bool TpmInit::SetupTpm(bool load_key) {
+  if (get_tpm()->IsInitialized()) {
+    return false;
+  }
+  get_tpm()->SetIsInitialized(true);
+
+  MigrateStatusFiles();
+
+  // Checking disabled and owned either via sysfs or via TSS calls will block if
+  // ownership is being taken by another thread or process.  So for this to work
+  // well, SetupTpm() needs to be called before InitializeTpm() is called.  At
+  // that point, the public API for Tpm only checks these booleans, so other
+  // threads can check without being blocked.  InitializeTpm() will reset the
+  // TPM's is_owned_ bit on success.
+  bool is_enabled = false;
+  bool is_owned = false;
+  bool successful_check = false;
+  if (platform_->FileExists(kTpmCheckEnabledFile)) {
+    is_enabled = IsEnabledCheckViaSysfs();
+    is_owned = IsOwnedCheckViaSysfs();
+    successful_check = true;
+  } else {
+    if (get_tpm()->PerformEnabledOwnedCheck(&is_enabled, &is_owned)) {
+      successful_check = true;
+    }
+  }
+
+  get_tpm()->SetIsOwned(is_owned);
+  get_tpm()->SetIsEnabled(is_enabled);
+
+  if (successful_check && !is_owned) {
+    platform_->DeleteFile(kOpenCryptokiPath, true);
+    platform_->DeleteFile(kTpmOwnedFile, false);
+    platform_->DeleteFile(kTpmStatusFile, false);
+  }
+  if (successful_check && is_owned) {
+    if (!platform_->FileExists(kTpmOwnedFile)) {
+      chromeos::Blob empty_blob(0);
+      platform_->WriteFile(kTpmOwnedFile, empty_blob);
+    }
+  }
+
+  TpmStatus tpm_status;
+  if (LoadTpmStatus(&tpm_status)) {
+    if (tpm_status.has_owner_password()) {
+      SecureBlob local_owner_password;
+      if (LoadOwnerPassword(tpm_status, &local_owner_password)) {
+        get_tpm()->SetOwnerPassword(local_owner_password);
+      }
+    }
+  }
+
+  if (load_key) {
+    // load cryptohome key
+    TSS_HCONTEXT context_handle = get_tpm()->ConnectContext();
+    if (context_handle) {
+      TSS_HKEY key_handle;
+      TSS_RESULT result;
+      if (LoadOrCreateCryptohomeKey(
+          context_handle, &key_handle, &result)) {
+        cryptohome_context_.reset(0, context_handle);
+        cryptohome_key_.reset(context_handle, key_handle);
+      } else {
+        get_tpm()->CloseContext(context_handle);
+      }
+    }
+  }
+
+  return true;
+}
+
+bool TpmInit::InitializeTpm(bool* OUT_took_ownership) {
+  TpmStatus tpm_status;
+
+  if (!LoadTpmStatus(&tpm_status)) {
+    tpm_status.Clear();
+    tpm_status.set_flags(TpmStatus::NONE);
+  }
+
+  if (OUT_took_ownership) {
+    *OUT_took_ownership = false;
+  }
+
+  if (!IsTpmEnabled()) {
+    return false;
+  }
+
+  trousers::ScopedTssContext context_handle;
+  if (!(*(context_handle.ptr()) = get_tpm()->ConnectContext())) {
+    LOG(ERROR) << "Failed to connect to TPM";
+    return false;
+  }
+
+  SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
+  memcpy(default_owner_password.data(), kTpmWellKnownPassword,
+         sizeof(kTpmWellKnownPassword));
+
+  bool took_ownership = false;
+  if (!IsTpmOwned()) {
+    SetTpmBeingOwned(true);
+    platform_->DeleteFile(kOpenCryptokiPath, true);
+    platform_->DeleteFile(kTpmOwnedFile, false);
+    platform_->DeleteFile(kTpmStatusFile, false);
+
+    if (!get_tpm()->IsEndorsementKeyAvailable(context_handle)) {
+      if (!get_tpm()->CreateEndorsementKey(context_handle)) {
+        LOG(ERROR) << "Failed to create endorsement key";
+        SetTpmBeingOwned(false);
+        return false;
+      }
+    }
+
+    if (!get_tpm()->IsEndorsementKeyAvailable(context_handle)) {
+      LOG(ERROR) << "Endorsement key is not available";
+      SetTpmBeingOwned(false);
+      return false;
+    }
+
+    if (!get_tpm()->TakeOwnership(context_handle, kMaxTimeoutRetries,
+                                  default_owner_password)) {
+      LOG(ERROR) << "Take Ownership failed";
+      SetTpmBeingOwned(false);
+      return false;
+    }
+
+    SetTpmOwned(true);
+    took_ownership = true;
+
+    tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
+                         TpmStatus::USES_WELL_KNOWN_OWNER |
+                         TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
+                         TpmStatus::ATTESTATION_NEEDS_OWNER);
+    tpm_status.clear_owner_password();
+    StoreTpmStatus(tpm_status);
+  }
+
+  if (OUT_took_ownership) {
+    *OUT_took_ownership = took_ownership;
+  }
+
+  // If we can open the TPM with the default password, then we still need to
+  // zero the SRK password and unrestrict it, then change the owner password.
+  TSS_HTPM tpm_handle;
+  if (!platform_->FileExists(kTpmOwnedFile) &&
+      get_tpm()->GetTpmWithAuth(context_handle,
+                                default_owner_password,
+                                &tpm_handle) &&
+      get_tpm()->TestTpmAuth(tpm_handle)) {
+    if (!get_tpm()->ZeroSrkPassword(context_handle, default_owner_password)) {
+      LOG(ERROR) << "Couldn't zero SRK password";
+      SetTpmBeingOwned(false);
+      return false;
+    }
+
+    if (!get_tpm()->UnrestrictSrk(context_handle, default_owner_password)) {
+      LOG(ERROR) << "Couldn't unrestrict the SRK";
+      SetTpmBeingOwned(false);
+      return false;
+    }
+
+    SecureBlob owner_password;
+    CreateOwnerPassword(&owner_password);
+
+    tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
+                         TpmStatus::USES_RANDOM_OWNER |
+                         TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
+                         TpmStatus::ATTESTATION_NEEDS_OWNER);
+    if (!StoreOwnerPassword(owner_password, &tpm_status)) {
+      tpm_status.clear_owner_password();
+    }
+    StoreTpmStatus(tpm_status);
+
+    if ((get_tpm()->ChangeOwnerPassword(context_handle,
+                                        default_owner_password,
+                                        owner_password))) {
+      get_tpm()->SetOwnerPassword(owner_password);
+    }
+    chromeos::Blob empty_blob(0);
+    platform_->WriteFile(kTpmOwnedFile, empty_blob);
+  } else {
+    // If we fall through here, then the TPM owned file doesn't exist, but we
+    // couldn't auth with the well-known password.  In this case, we must assume
+    // that the TPM has already been owned and set to a random password, so
+    // touch the TPM owned file.
+    if (!platform_->FileExists(kTpmOwnedFile)) {
+      chromeos::Blob empty_blob(0);
+      platform_->WriteFile(kTpmOwnedFile, empty_blob);
+    }
+  }
+
+  SetTpmBeingOwned(false);
+  return true;
+}
+
+bool TpmInit::LoadTpmStatus(TpmStatus* serialized) {
+  if (!platform_->FileExists(kTpmStatusFile)) {
+    return false;
+  }
+  SecureBlob file_data;
+  if (!platform_->ReadFile(kTpmStatusFile, &file_data)) {
+    return false;
+  }
+  if (!serialized->ParseFromArray(
+           static_cast<const unsigned char*>(file_data.data()),
+           file_data.size())) {
+    return false;
+  }
+  return true;
+}
+
+bool TpmInit::StoreTpmStatus(const TpmStatus& serialized) {
+  int old_mask = platform_->SetMask(kDefaultUmask);
+  if (platform_->FileExists(kTpmStatusFile)) {
+    do {
+      int64 file_size;
+      if (!platform_->GetFileSize(kTpmStatusFile, &file_size)) {
+        break;
+      }
+      SecureBlob random;
+      if (!get_tpm()->GetRandomData(file_size, &random)) {
+        break;
+      }
+      FILE* file = platform_->OpenFile(kTpmStatusFile, "wb+");
+      if (!file) {
+        break;
+      }
+      if (!platform_->WriteOpenFile(file, random)) {
+        platform_->CloseFile(file);
+        break;
+      }
+      platform_->CloseFile(file);
+    } while (false);
+    platform_->DeleteFile(kTpmStatusFile, false);
+  }
+  SecureBlob final_blob(serialized.ByteSize());
+  serialized.SerializeWithCachedSizesToArray(
+      static_cast<google::protobuf::uint8*>(final_blob.data()));
+  bool ok = platform_->WriteFile(kTpmStatusFile, final_blob);
+  platform_->SetMask(old_mask);
+  return ok;
+}
+
+void TpmInit::CreateOwnerPassword(SecureBlob* password) {
+  // Generate a random owner password.  The default is a 12-character,
+  // hex-encoded password created from 6 bytes of random data.
+  SecureBlob random(kOwnerPasswordLength / 2);
+  CryptoLib::GetSecureRandom(static_cast<unsigned char*>(random.data()),
+                             random.size());
+  SecureBlob tpm_password(kOwnerPasswordLength);
+  CryptoLib::AsciiEncodeToBuffer(random,
+                                 static_cast<char*>(tpm_password.data()),
+                                 tpm_password.size());
+  password->swap(tpm_password);
+}
+
+bool TpmInit::LoadOwnerPassword(const TpmStatus& tpm_status,
+                                chromeos::Blob* owner_password) {
+  if (!(tpm_status.flags() & TpmStatus::OWNED_BY_THIS_INSTALL)) {
+    return false;
+  }
+  if ((tpm_status.flags() & TpmStatus::USES_WELL_KNOWN_OWNER)) {
+    SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
+    memcpy(default_owner_password.data(), kTpmWellKnownPassword,
+           sizeof(kTpmWellKnownPassword));
+    owner_password->swap(default_owner_password);
+    return true;
+  }
+  if (!(tpm_status.flags() & TpmStatus::USES_RANDOM_OWNER) ||
+      !tpm_status.has_owner_password()) {
+    return false;
+  }
+
+  SecureBlob local_owner_password(tpm_status.owner_password().length());
+  tpm_status.owner_password().copy(
+      static_cast<char*>(local_owner_password.data()),
+      tpm_status.owner_password().length(), 0);
+  if (!get_tpm()->Unseal(local_owner_password, owner_password)) {
+    LOG(ERROR) << "Failed to unseal the owner password.";
+    return false;
+  }
+  return true;
+}
+
+bool TpmInit::StoreOwnerPassword(const chromeos::Blob& owner_password,
+                                 TpmStatus* tpm_status) {
+  // Use PCR0 when sealing the data so that the owner password is only
+  // available in the current boot mode.  This helps protect the password from
+  // offline attacks until it has been presented and cleared.
+  SecureBlob sealed_password;
+  if (!get_tpm()->SealToPCR0(owner_password, &sealed_password)) {
+    LOG(ERROR) << "StoreOwnerPassword: Failed to seal owner password.";
+    return false;
+  }
+  tpm_status->set_owner_password(sealed_password.data(),
+                                 sealed_password.size());
+  return true;
+}
+
+void TpmInit::RemoveTpmOwnerDependency(TpmOwnerDependency dependency) {
+  int32 flag_to_clear = TpmStatus::NONE;
+  switch (dependency) {
+    case kInstallAttributes:
+      flag_to_clear = TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER;
+      break;
+    case kAttestation:
+      flag_to_clear = TpmStatus::ATTESTATION_NEEDS_OWNER;
+      break;
+    default:
+      CHECK(false);
+  }
+  TpmStatus tpm_status;
+  if (!LoadTpmStatus(&tpm_status))
+    return;
+  tpm_status.set_flags(tpm_status.flags() & ~flag_to_clear);
+  StoreTpmStatus(tpm_status);
+}
+
+bool TpmInit::CheckSysfsForOne(const char* file_name) const {
+  std::string contents;
+  if (!platform_->ReadFileToString(file_name, &contents)) {
+    return false;
+  }
+  if (contents.size() < 1) {
+    return false;
+  }
+  return (contents[0] == '1');
+}
+
+bool TpmInit::IsEnabledCheckViaSysfs() {
+  return CheckSysfsForOne(kTpmCheckEnabledFile);
+}
+
+bool TpmInit::IsOwnedCheckViaSysfs() {
+  return CheckSysfsForOne(kTpmCheckOwnedFile);
+}
+
+bool TpmInit::CreateCryptohomeKey(TSS_HCONTEXT context_handle) {
+  chromeos::SecureBlob wrapped_key;
+  if (!get_tpm()->CreateWrappedRsaKey(context_handle, &wrapped_key)) {
+    LOG(ERROR) << "Couldn't create cryptohome key";
+    return false;
+  }
+
+  if (!SaveCryptohomeKey(wrapped_key)) {
+    LOG(ERROR) << "Couldn't save cryptohome key";
+    return false;
+  }
+
+  LOG(INFO) << "Created new cryptohome key.";
+  return true;
+}
+
+bool TpmInit::SaveCryptohomeKey(const chromeos::SecureBlob& raw_key) {
+  int previous_mask = platform_->SetMask(cryptohome::kDefaultUmask);
+  bool ok = platform_->WriteFile(kDefaultCryptohomeKeyFile, raw_key);
+  platform_->SetMask(previous_mask);
+  if (!ok)
+    LOG(ERROR) << "Error writing key file of desired size: " << raw_key.size();
+  return ok;
+}
+
+bool TpmInit::LoadCryptohomeKey(TSS_HCONTEXT context_handle,
+                                TSS_HKEY* key_handle,
+                                TSS_RESULT* result) {
+  // First, try loading the key from the key file
+  {
+    SecureBlob raw_key;
+    if (platform_->ReadFile(kDefaultCryptohomeKeyFile, &raw_key)) {
+      if (get_tpm()->LoadWrappedKey(context_handle,
+                                    raw_key,
+                                    key_handle,
+                                    result)) {
+        return true;
+      }
+      if (get_tpm()->IsTransient(*result)) {
+        return false;
+      }
+    }
+  }
+
+  // Then try loading the key by the UUID (this is a legacy upgrade path)
+  SecureBlob raw_key;
+  trousers::ScopedTssKey local_key_handle(context_handle);
+  if (!get_tpm()->LoadKeyByUuid(context_handle,
+                               kCryptohomeWellKnownUuid,
+                               local_key_handle.ptr(),
+                               &raw_key,
+                               result)) {
+    return false;
+  }
+
+  // Save the cryptohome key to the well-known location
+  if (!SaveCryptohomeKey(raw_key)) {
+    LOG(ERROR) << "Couldn't save cryptohome key";
+    return false;
+  }
+
+  *key_handle = local_key_handle.release();
+
+  return true;
+}
+
+bool TpmInit::LoadOrCreateCryptohomeKey(TSS_HCONTEXT context_handle,
+                                        TSS_HKEY* key_handle,
+                                        TSS_RESULT* result) {
+  *result = TSS_SUCCESS;
+
+  // Try to load the cryptohome key.
+  if (LoadCryptohomeKey(context_handle, key_handle, result)) {
+    return true;
+  }
+
+  // If the error is expected to be transient, return now.
+  if (get_tpm()->IsTransient(*result)) {
+    LOG(INFO) << "Transient failure loading cryptohome key";
+    return false;
+  }
+
+  // Otherwise, the key couldn't be loaded, and it wasn't due to a transient
+  // error, so we must create the key.
+  if (CreateCryptohomeKey(context_handle)) {
+    if (LoadCryptohomeKey(context_handle, key_handle, result)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool TpmInit::HasCryptohomeKey() {
+  return cryptohome_context_.value() && cryptohome_key_.value();
+}
+
+TSS_HCONTEXT TpmInit::GetCryptohomeContext() {
+  return cryptohome_context_.value();
+}
+
+TSS_HKEY TpmInit::GetCryptohomeKey() {
+  return cryptohome_key_.value();
+}
+
 }  // namespace cryptohome
diff --git a/tpm_init.h b/tpm_init.h
index 091dd2c..5634a7d 100644
--- a/tpm_init.h
+++ b/tpm_init.h
@@ -7,10 +7,10 @@
 #include <base/basictypes.h>
 #include <base/memory/scoped_ptr.h>
 #include <chromeos/utility.h>
+#include <trousers/scoped_tss_type.h>
 
-#include "attestation.h"
-#include "crypto.h"
 #include "tpm.h"
+#include "tpm_status.pb.h"
 
 #ifndef CRYPTOHOME_TPM_INIT_H_
 #define CRYPTOHOME_TPM_INIT_H_
@@ -26,27 +26,56 @@
   // PlatformThread::Delegate
   friend class TpmInitTask;
  public:
+  enum TpmOwnerDependency {
+      kInstallAttributes,
+      kAttestation
+  };
+
   class TpmInitCallback {
    public:
     virtual void InitializeTpmComplete(bool status, bool took_ownership) = 0;
   };
 
   // Default constructor
-  explicit TpmInit(Platform* platform);
+  TpmInit(Tpm* tpm, Platform* platform);
 
   virtual ~TpmInit();
 
   virtual void Init(TpmInitCallback* notify_callback);
 
-  // Gets random data from the TPM
+  // Sets the TPM to the state where we last left it in. This must be called
+  // before the *InitializeTpm functions below, if we need to.
   //
-  // Parameters
-  //   length - The number of bytes to get
-  //   data (OUT) - Receives the random bytes
-  virtual bool GetRandomData(int length, chromeos::Blob* data);
+  // Parameters:
+  //   load_key - TRUE to load load Cryptohome key.
+  //
+  // Returns false if the instance has already been setup.
+  virtual bool SetupTpm(bool load_key);
 
-  // Starts asynchronous initialization of the TPM
-  virtual bool StartInitializeTpm();
+  // Asynchronously initializes the TPM. The TPM is initialized following these
+  // steps:
+  //
+  //   1. The TPM is owned with default owner password.
+  //   2. The SRK password is cleared. The SRK is then unrestricted.
+  //   3. New owner password is established.
+  //   4. (This new password WILL be wiped later when all owner dependencies
+  //       have been removed.)
+  //
+  // At each step in the process, a status file is updated so that we can
+  // resume the initialization later (see SetupTpm above).
+  //
+  // The initialization is usually done asynchronously. Attestation and
+  // InstallAttributes must remove themselves from owner dependency list so that
+  // the owner password can be cleared.
+  //
+  // Returns true if a thread was spawn to do the actual initialization.
+  virtual bool AsyncInitializeTpm();
+
+  // Synchronously initializes the TPM.
+  //
+  // Returns true if the TPM initialization process (as outlined above) is
+  // completed at step 3.
+  virtual bool InitializeTpm(bool* OUT_took_ownership);
 
   // Returns true if the TPM is initialized and ready for use
   virtual bool IsTpmReady();
@@ -57,9 +86,15 @@
   // Returns true if the TPM is owned
   virtual bool IsTpmOwned();
 
+  // Marks the TPM as being owned
+  virtual void SetTpmOwned(bool owned);
+
   // Returns true if the TPM is being owned
   virtual bool IsTpmBeingOwned();
 
+  // Marks the TPM as being or not being been owned
+  virtual void SetTpmBeingOwned(bool being_owned);
+
   // Returns true if initialization has been called
   virtual bool HasInitializeBeenCalled();
 
@@ -72,13 +107,71 @@
   // Clears the TPM password from memory and disk
   virtual void ClearStoredTpmPassword();
 
+  // Removes the given owner dependency. When all dependencies have been removed
+  // the owner password can be cleared.
+  //
+  // Parameters
+  //   dependency - The dependency (on TPM ownership) to be removed
+  virtual void RemoveTpmOwnerDependency(TpmOwnerDependency dependency);
+
   virtual void set_tpm(Tpm* value);
 
   virtual Tpm* get_tpm();
 
+  virtual bool HasCryptohomeKey();
+
+  virtual TSS_HCONTEXT GetCryptohomeContext();
+
+  virtual TSS_HKEY GetCryptohomeKey();
+
  private:
   virtual void ThreadMain();
 
+  // Loads the TpmStatus object
+  bool LoadTpmStatus(TpmStatus* serialized);
+
+  // Saves the TpmStatus object
+  bool StoreTpmStatus(const TpmStatus& serialized);
+
+  // Creates a random owner password
+  //
+  // Parameters
+  //   password (OUT) - the generated password
+  void CreateOwnerPassword(chromeos::SecureBlob* password);
+
+  // Stores the TPM owner password to the TpmStatus object
+  bool StoreOwnerPassword(const chromeos::Blob& owner_password,
+                          TpmStatus* tpm_status);
+
+  // Retrieves the TPM owner password
+  bool LoadOwnerPassword(const TpmStatus& tpm_status,
+                         chromeos::Blob* owner_password);
+
+  // Migrate any TPM status files from old location to new location.
+  void MigrateStatusFiles();
+
+  // Returns whether or not the TPM is enabled by checking a flag in the TPM's
+  // entry in /sys/class/misc
+  bool IsEnabledCheckViaSysfs();
+
+  // Returns whether or not the TPM is owned by checking a flag in the TPM's
+  // entry in /sys/class/misc
+  bool IsOwnedCheckViaSysfs();
+
+  bool SaveCryptohomeKey(const chromeos::SecureBlob& wrapped_key);
+
+  bool LoadCryptohomeKey(TSS_HCONTEXT context_handle, TSS_HKEY* key_handle,
+                         TSS_RESULT* result);
+
+  bool CreateCryptohomeKey(TSS_HCONTEXT context_handle);
+
+  bool LoadOrCreateCryptohomeKey(TSS_HCONTEXT context_handle,
+                                 TSS_HKEY* key_handle,
+                                 TSS_RESULT* result);
+
+  // Returns true if the first byte of the file |file_name| is "1"
+  bool CheckSysfsForOne(const char* file_name) const;
+
   // The background task for initializing the TPM, implemented as a
   // PlatformThread::Delegate
   scoped_ptr<TpmInitTask> tpm_init_task_;
@@ -90,6 +183,8 @@
   bool initialize_took_ownership_;
   int64_t initialization_time_;
   Platform* platform_;
+  trousers::ScopedTssContext cryptohome_context_;
+  trousers::ScopedTssKey cryptohome_key_;
 
   DISALLOW_COPY_AND_ASSIGN(TpmInit);
 };