Adds the necessary changes to tpm_init to allow triggered initialization.
Change-Id: I757a112ef011ee9688f695cdd89ad2786c47778b
BUG=3065
TEST=
Review URL: http://codereview.chromium.org/3475009
diff --git a/SConstruct b/SConstruct
index 603beef..da56dd2 100644
--- a/SConstruct
+++ b/SConstruct
@@ -5,13 +5,51 @@
import os
import sys
+# Borrowed from updater
+# Protobuffer compilation
+def ProtocolBufferEmitter(target, source, env):
+ """ Inputs:
+ target: list of targets to compile to
+ source: list of sources to compile
+ env: the scons environment in which we are compiling
+ Outputs:
+ target: the list of targets we'll emit
+ source: the list of sources we'll compile"""
+ output = str(source[0])
+ output = output[0:output.rfind('.proto')]
+ target = [
+ output + '.pb.cc',
+ output + '.pb.h',
+ ]
+ return target, source
+
+def ProtocolBufferGenerator(source, target, env, for_signature):
+ """ Inputs:
+ source: list of sources to process
+ target: list of targets to generate
+ env: scons environment in which we are working
+ for_signature: unused
+ Outputs: a list of commands to execute to generate the targets from
+ the sources."""
+ commands = [
+ '/usr/bin/protoc '
+ ' --proto_path . ${SOURCES} --cpp_out .']
+ return commands
+
+proto_builder = Builder(generator = ProtocolBufferGenerator,
+ emitter = ProtocolBufferEmitter,
+ single_source = 1,
+ suffix = '.pb.cc')
+
env = Environment()
# setup sources
lib_sources = env.Split("""crypto.cc
+ platform.cc
secure_blob.cc
tpm.cc
tpm_init.cc
+ tpm_status.pb.cc
""")
client_sources = env.Split("""main.cc
""") + lib_sources
@@ -20,7 +58,7 @@
CPPPATH=['.', '..'],
CPPFLAGS=['-pie', '-fstack-protector-all', '-fPIC',
'-fno-exceptions', '-O2', '-Wall', '-Werror'],
- LIBS = ['base', 'chromeos', 'crypto', 'rt', 'pthread', 'tspi'],
+ LIBS = ['base', 'chromeos', 'crypto', 'rt', 'protobuf', 'pthread', 'tspi'],
)
for key in Split('CC CXX AR RANLIB LD NM CFLAGS CCFLAGS'):
value = os.environ.get(key)
@@ -32,8 +70,11 @@
if os.environ.has_key(key):
env['ENV'][key] = os.environ[key]
+env['BUILDERS']['ProtocolBuffer'] = proto_builder
+
env.Append(LIBPATH = ['.'])
env_lib = env.Clone()
+env_lib.ProtocolBuffer('tpm_status.pb.cc', 'tpm_status.proto')
env_lib.Library('tpm_init', lib_sources)
diff --git a/platform.cc b/platform.cc
new file mode 100644
index 0000000..b07590f
--- /dev/null
+++ b/platform.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2009-2010 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.
+
+// Contains the implementation of class Platform
+
+#include "platform.h"
+
+#include <errno.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace tpm_init {
+
+const int kDefaultUmask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH
+ | S_IXOTH;
+
+Platform::Platform()
+ : umask_(kDefaultUmask) {
+}
+
+Platform::~Platform() {
+}
+
+int Platform::SetMask(int new_mask) {
+ return umask(new_mask);
+}
+
+} // namespace tpm_init
diff --git a/platform.h b/platform.h
new file mode 100644
index 0000000..e94412a
--- /dev/null
+++ b/platform.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2009-2010 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 TPM_INIT_PLATFORM_H_
+#define TPM_INIT_PLATFORM_H_
+
+#include <base/basictypes.h>
+#include <string>
+#include <vector>
+
+namespace tpm_init {
+
+// Default umask
+extern const int kDefaultUmask;
+
+// Class Platform exists to be able to mock platform calls (in this case, just
+// umask).
+// TODO(fes): Remove this class altogether if tpm_init is merged with
+// cryptohome, or put it in a separate, common library.
+class Platform {
+ public:
+
+ Platform();
+
+ virtual ~Platform();
+
+ // Sets the current umask, returning the old mask
+ //
+ // Parameters
+ // new_mask - The mask to set
+ virtual int SetMask(int new_mask);
+
+ private:
+ int umask_;
+
+ DISALLOW_COPY_AND_ASSIGN(Platform);
+};
+
+} // namespace tpm_init
+
+#endif // TPM_INIT_PLATFORM_H_
diff --git a/tpm.cc b/tpm.cc
index 1efa15c..1f7d75c 100644
--- a/tpm.cc
+++ b/tpm.cc
@@ -14,6 +14,10 @@
#include <trousers/trousers.h>
namespace tpm_init {
+#define TPM_LOG(severity, result) \
+ LOG(severity) << "TPM error 0x" << std::hex << result \
+ << " (" << Trspi_Error_String(result) << "): "
+
const char* kWellKnownSrkTmp = "1234567890";
const int kOwnerPasswordLength = 12;
@@ -21,15 +25,19 @@
const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled";
const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned";
const char* kTpmOwnedFile = "/var/lib/.tpm_owned";
+const char* kTpmStatusFile = "/var/lib/.tpm_status";
const char* kOpenCryptokiPath = "/var/lib/opencryptoki";
const int kTpmConnectRetries = 10;
const int kTpmConnectIntervalMs = 100;
const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET;
+const char kTpmOwnedWithWellKnown = 'W';
+const char kTpmOwnedWithRandom = 'R';
Tpm::Tpm()
- : context_handle_(0),
- default_crypto_(new Crypto()),
+ : default_crypto_(new Crypto()),
crypto_(default_crypto_.get()),
+ default_platform_(new Platform()),
+ platform_(default_platform_.get()),
owner_password_(),
password_sync_lock_(),
is_disabled_(true),
@@ -39,7 +47,6 @@
}
Tpm::~Tpm() {
- Disconnect();
}
bool Tpm::Init() {
@@ -49,9 +56,11 @@
// 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 (file_util::PathExists(FilePath(kTpmCheckEnabledFile))) {
is_disabled_ = IsDisabledCheckViaSysfs();
is_owned_ = IsOwnedCheckViaSysfs();
+ successful_check = true;
} else {
TSS_HCONTEXT context_handle;
if (OpenAndConnectTpm(&context_handle)) {
@@ -61,101 +70,55 @@
is_disabled_ = !enabled;
is_owned_ = owned;
Tspi_Context_Close(context_handle);
- } else {
+ successful_check = true;
}
}
- return true;
-}
-
-bool Tpm::Connect() {
- if (context_handle_ == 0) {
- TSS_HCONTEXT context_handle;
- if (!OpenAndConnectTpm(&context_handle)) {
- return false;
+ if (successful_check && !is_owned_) {
+ file_util::Delete(FilePath(kOpenCryptokiPath), true);
+ file_util::Delete(FilePath(kTpmOwnedFile), false);
+ file_util::Delete(FilePath(kTpmStatusFile), false);
+ }
+ 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();
+ }
}
-
- context_handle_ = context_handle;
}
return true;
}
-bool Tpm::IsConnected() {
- return (context_handle_ != 0);
+TSS_HCONTEXT Tpm::Connect() {
+ TSS_HCONTEXT context_handle;
+ if (!OpenAndConnectTpm(&context_handle)) {
+ return NULL;
+ }
+
+ return context_handle;
}
-void Tpm::Disconnect() {
- if (context_handle_) {
- Tspi_Context_Close(context_handle_);
- context_handle_ = 0;
+void Tpm::Disconnect(TSS_HCONTEXT context_handle) {
+ if (context_handle) {
+ Tspi_Context_Close(context_handle);
}
}
int Tpm::GetMaxRsaKeyCount() {
- if (context_handle_ == 0) {
+ TSS_HCONTEXT context_handle = Connect();
+ if (!context_handle) {
return -1;
}
-
- return GetMaxRsaKeyCountForContext(context_handle_);
-}
-
-int Tpm::GetMaxRsaKeyCountForContext(TSS_HCONTEXT context_handle) {
- int count = -1;
- TSS_RESULT result;
- TSS_HTPM tpm_handle;
- if (!GetTpm(context_handle, &tpm_handle)) {
- return count;
- }
-
- UINT32 cap_length = 0;
- BYTE* cap = NULL;
- UINT32 subcap = TSS_TPMCAP_PROP_MAXKEYS;
- if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY,
- sizeof(subcap),
- reinterpret_cast<BYTE*>(&subcap),
- &cap_length, &cap))) {
- LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result;
- return count;
- }
- if (cap_length == sizeof(int)) {
- count = *(reinterpret_cast<int*>(cap));
- }
- Tspi_Context_FreeMemory(context_handle, cap);
+ int count = GetMaxRsaKeyCountForContext(context_handle);
+ Disconnect(context_handle);
return count;
}
-bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
- TSS_RESULT result;
- TSS_HCONTEXT local_context_handle;
- if ((result = Tspi_Context_Create(&local_context_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_Create";
- return false;
- }
-
- for (int i = 0; i < kTpmConnectRetries; i++) {
- if ((result = Tspi_Context_Connect(local_context_handle, NULL))) {
- if (result == TSS_E_COMM_FAILURE) {
- PlatformThread::Sleep(kTpmConnectIntervalMs);
- } else {
- LOG(ERROR) << "Error calling Tspi_Context_Connect: " << result;
- Tspi_Context_Close(local_context_handle);
- return false;
- }
- } else {
- break;
- }
- }
-
- if (result) {
- LOG(ERROR) << "Error calling Tspi_Context_Connect: " << result;
- Tspi_Context_Close(local_context_handle);
- return false;
- }
-
- *context_handle = local_context_handle;
- return true;
-}
-
bool Tpm::IsDisabledCheckViaSysfs() {
std::string contents;
if (!file_util::ReadFileToString(FilePath(kTpmCheckEnabledFile), &contents)) {
@@ -178,6 +141,63 @@
return (contents[0] != '0');
}
+int Tpm::GetMaxRsaKeyCountForContext(TSS_HCONTEXT context_handle) {
+ int count = -1;
+ TSS_RESULT result;
+ TSS_HTPM tpm_handle;
+ if (!GetTpm(context_handle, &tpm_handle)) {
+ return count;
+ }
+
+ UINT32 cap_length = 0;
+ BYTE* cap = NULL;
+ UINT32 subcap = TSS_TPMCAP_PROP_MAXKEYS;
+ if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY,
+ sizeof(subcap),
+ reinterpret_cast<BYTE*>(&subcap),
+ &cap_length, &cap))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
+ return count;
+ }
+ if (cap_length == sizeof(int)) {
+ count = *(reinterpret_cast<int*>(cap));
+ }
+ Tspi_Context_FreeMemory(context_handle, cap);
+ return count;
+}
+
+bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
+ TSS_RESULT result;
+ TSS_HCONTEXT local_context_handle;
+ if ((result = Tspi_Context_Create(&local_context_handle))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Create";
+ return false;
+ }
+
+ for (int i = 0; i < kTpmConnectRetries; i++) {
+ if ((result = Tspi_Context_Connect(local_context_handle, NULL))) {
+ if (result == TSS_E_COMM_FAILURE) {
+ PlatformThread::Sleep(kTpmConnectIntervalMs);
+ } else {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Connect";
+ Tspi_Context_Close(local_context_handle);
+ return false;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (result) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Connect";
+ Tspi_Context_Close(local_context_handle);
+ return false;
+ }
+
+ *context_handle = local_context_handle;
+ return true;
+}
+
void Tpm::IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle,
bool* enabled, bool* owned) {
*enabled = false;
@@ -218,13 +238,13 @@
if ((result = Tspi_Context_CreateObject(context_handle,
TSS_OBJECT_TYPE_RSAKEY,
init_flags, &local_key_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
return false;
}
if ((result = Tspi_TPM_CreateEndorsementKey(tpm_handle, local_key_handle,
NULL))) {
- LOG(ERROR) << "Error calling Tspi_TPM_CreateEndorsementKey: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_CreateEndorsementKey";
Tspi_Context_CloseObject(context_handle, local_key_handle);
return false;
}
@@ -242,7 +262,7 @@
TSS_HKEY local_key_handle;
if ((result = Tspi_TPM_GetPubEndorsementKey(tpm_handle, false, NULL,
&local_key_handle))) {
- LOG(ERROR) << "Error calling Tspi_TPM_GetPubEndorsementKey: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetPubEndorsementKey";
return false;
}
@@ -252,7 +272,9 @@
}
void Tpm::CreateOwnerPassword(SecureBlob* password) {
- SecureBlob random(kOwnerPasswordLength);
+ // 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);
crypto_->GetSecureRandom(static_cast<unsigned char*>(random.data()),
random.size());
SecureBlob tpm_password(kOwnerPasswordLength);
@@ -274,14 +296,14 @@
if ((result = Tspi_Context_CreateObject(context_handle,
TSS_OBJECT_TYPE_RSAKEY,
init_flags, &srk_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
return false;
}
TSS_HPOLICY srk_usage_policy;
if ((result = Tspi_GetPolicyObject(srk_handle, TSS_POLICY_USAGE,
&srk_usage_policy))) {
- LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
Tspi_Context_CloseObject(context_handle, srk_handle);
return false;
}
@@ -290,7 +312,7 @@
TSS_SECRET_MODE_PLAIN,
strlen(kWellKnownSrkTmp),
const_cast<BYTE *>(reinterpret_cast<const BYTE *>(kWellKnownSrkTmp))))) {
- LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
Tspi_Context_CloseObject(context_handle, srk_handle);
return false;
}
@@ -305,8 +327,8 @@
(retry_count < max_timeout_tries));
if (result) {
- LOG(ERROR) << "Error calling Tspi_TPM_TakeOwnership: " << result
- << ", attempts: " << retry_count;
+ TPM_LOG(ERROR, result)
+ << "Error calling Tspi_TPM_TakeOwnership, attempts: " << retry_count;
Tspi_Context_CloseObject(context_handle, srk_handle);
return false;
}
@@ -328,7 +350,7 @@
TSS_UUID SRK_UUID = TSS_UUID_SRK;
if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM,
SRK_UUID, &srk_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_LoadKeyByUUID: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_LoadKeyByUUID";
return false;
}
@@ -337,7 +359,7 @@
TSS_OBJECT_TYPE_POLICY,
TSS_POLICY_USAGE,
&policy_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
Tspi_Context_CloseObject(context_handle, srk_handle);
return false;
}
@@ -345,7 +367,7 @@
BYTE new_password[0];
if ((result = Tspi_Policy_SetSecret(policy_handle, TSS_SECRET_MODE_PLAIN,
0, new_password))) {
- LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
Tspi_Context_CloseObject(context_handle, policy_handle);
Tspi_Context_CloseObject(context_handle, srk_handle);
return false;
@@ -354,7 +376,7 @@
if ((result = Tspi_ChangeAuth(srk_handle,
tpm_handle,
policy_handle))) {
- LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
Tspi_Context_CloseObject(context_handle, policy_handle);
Tspi_Context_CloseObject(context_handle, srk_handle);
return false;
@@ -366,7 +388,7 @@
}
bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle,
- const SecureBlob& owner_password) {
+ const SecureBlob& owner_password) {
TSS_RESULT result;
TSS_HTPM tpm_handle;
if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) {
@@ -378,7 +400,7 @@
if ((result = Tspi_TPM_GetStatus(tpm_handle,
TSS_TPMSTATUS_DISABLEPUBSRKREAD,
¤t_status))) {
- LOG(ERROR) << "Error calling Tspi_TPM_GetStatus: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetStatus";
return false;
}
@@ -387,7 +409,7 @@
if ((result = Tspi_TPM_SetStatus(tpm_handle,
TSS_TPMSTATUS_DISABLEPUBSRKREAD,
false))) {
- LOG(ERROR) << "Error calling Tspi_TPM_SetStatus: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_SetStatus";
return false;
}
}
@@ -409,7 +431,7 @@
TSS_OBJECT_TYPE_POLICY,
TSS_POLICY_USAGE,
&policy_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
return false;
}
@@ -418,17 +440,228 @@
owner_password.size(),
const_cast<BYTE *>(static_cast<const BYTE *>(
owner_password.const_data()))))) {
- LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
Tspi_Context_CloseObject(context_handle, policy_handle);
return false;
}
if ((result = Tspi_ChangeAuth(tpm_handle, 0, policy_handle))) {
- LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
Tspi_Context_CloseObject(context_handle, policy_handle);
return false;
}
+ Tspi_Context_CloseObject(context_handle, policy_handle);
+ return true;
+}
+
+// TODO(fes): This method is borrowed from cryptohome. When the tpm_init
+// library is merged into cryptohome, these duplicate methods need to be
+// removed. Either that, or they should be moved into a separate library.
+bool Tpm::LoadFileBytes(const FilePath& path, chromeos::Blob* blob) {
+ int64 file_size;
+ if (!file_util::PathExists(path)) {
+ return false;
+ }
+ if (!file_util::GetFileSize(path, &file_size)) {
+ LOG(ERROR) << "Could not get size of " << path.value();
+ return false;
+ }
+ // Compare to the max of a 32-bit signed integer
+ if (file_size > static_cast<int64>(INT_MAX)) {
+ LOG(ERROR) << "File " << path.value() << " is too large: " << file_size;
+ return false;
+ }
+ SecureBlob buf(file_size);
+ int data_read = file_util::ReadFile(path, reinterpret_cast<char*>(&buf[0]),
+ file_size);
+ // Cast is okay because of comparison to INT_MAX above
+ if (data_read != static_cast<int>(file_size)) {
+ LOG(ERROR) << "Could not read entire file " << file_size;
+ return false;
+ }
+ blob->swap(buf);
+ 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;
+ }
+
+ TSS_HCONTEXT context_handle;
+ if (!OpenAndConnectTpm(&context_handle)) {
+ return false;
+ }
+
+ TSS_RESULT result;
+ TSS_HKEY srk_handle;
+ if (!LoadSrk(context_handle, &srk_handle, &result)) {
+ LOG(ERROR) << "Error loading the SRK";
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ TSS_FLAG init_flags = TSS_ENCDATA_SEAL;
+ TSS_HKEY enc_handle;
+ if ((result = Tspi_Context_CreateObject(context_handle,
+ TSS_OBJECT_TYPE_ENCDATA,
+ init_flags, &enc_handle))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ 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 ((result = Tspi_SetAttribData(enc_handle,
+ TSS_TSPATTRIB_ENCDATA_BLOB,
+ TSS_TSPATTRIB_ENCDATABLOB_BLOB,
+ local_owner_password.size(),
+ static_cast<BYTE *>(local_owner_password.data())))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_SetAttribData";
+ Tspi_Context_CloseObject(context_handle, enc_handle);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ unsigned char* dec_data = NULL;
+ UINT32 dec_data_length = 0;
+ if ((result = Tspi_Data_Unseal(enc_handle, srk_handle, &dec_data_length,
+ &dec_data))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Data_Unseal";
+ Tspi_Context_CloseObject(context_handle, enc_handle);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ Tspi_Context_CloseObject(context_handle, enc_handle);
+
+ SecureBlob local_data(dec_data_length);
+ memcpy(static_cast<char*>(local_data.data()), dec_data, dec_data_length);
+ Tspi_Context_FreeMemory(context_handle, dec_data);
+
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+
+ owner_password->swap(local_data);
+
+ return true;
+}
+
+bool Tpm::StoreOwnerPassword(const chromeos::Blob& owner_password,
+ TpmStatus* tpm_status) {
+ TSS_HCONTEXT context_handle;
+ if (!OpenAndConnectTpm(&context_handle)) {
+ return false;
+ }
+
+ TSS_RESULT result;
+ TSS_HKEY srk_handle;
+ if (!LoadSrk(context_handle, &srk_handle, &result)) {
+ LOG(ERROR) << "Error loading the SRK";
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ // Check the SRK public key
+ unsigned int size_n;
+ BYTE *public_srk;
+ if ((result = Tspi_Key_GetPubKey(srk_handle, &size_n, &public_srk))) {
+ TPM_LOG(ERROR, result) << "Unable to get the SRK public key";
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+ Tspi_Context_FreeMemory(context_handle, public_srk);
+
+ TSS_HTPM tpm_handle;
+ if (!GetTpm(context_handle, &tpm_handle)) {
+ LOG(ERROR) << "Unable to get a handle to the TPM";
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ // 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.
+ TSS_HPCRS pcrs_handle;
+ if ((result = Tspi_Context_CreateObject(context_handle, TSS_OBJECT_TYPE_PCRS,
+ 0, &pcrs_handle))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ UINT32 pcr_len;
+ BYTE* pcr_value;
+ Tspi_TPM_PcrRead(tpm_handle, 0, &pcr_len, &pcr_value);
+ Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_len, pcr_value);
+ Tspi_Context_FreeMemory(context_handle, pcr_value);
+
+ TSS_FLAG init_flags = TSS_ENCDATA_SEAL;
+ TSS_HKEY enc_handle;
+ if ((result = Tspi_Context_CreateObject(context_handle,
+ TSS_OBJECT_TYPE_ENCDATA,
+ init_flags, &enc_handle))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
+ Tspi_Context_CloseObject(context_handle, pcrs_handle);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+
+ if ((result = Tspi_Data_Seal(enc_handle, srk_handle, owner_password.size(),
+ const_cast<BYTE *>(&owner_password[0]),
+ pcrs_handle))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Data_Seal";
+ Tspi_Context_CloseObject(context_handle, pcrs_handle);
+ Tspi_Context_CloseObject(context_handle, enc_handle);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+ Tspi_Context_CloseObject(context_handle, pcrs_handle);
+
+ unsigned char* enc_data = NULL;
+ UINT32 enc_data_length = 0;
+ if ((result = Tspi_GetAttribData(enc_handle, TSS_TSPATTRIB_ENCDATA_BLOB,
+ TSS_TSPATTRIB_ENCDATABLOB_BLOB,
+ &enc_data_length, &enc_data))) {
+ TPM_LOG(ERROR, result) << "Error calling Tspi_GetAttribData";
+ Tspi_Context_CloseObject(context_handle, enc_handle);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+ return false;
+ }
+ Tspi_Context_CloseObject(context_handle, enc_handle);
+
+ tpm_status->set_owner_password(enc_data, enc_data_length);
+
+ Tspi_Context_FreeMemory(context_handle, enc_data);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
+ Tspi_Context_Close(context_handle);
+
return true;
}
@@ -436,7 +669,7 @@
TSS_RESULT result;
TSS_HTPM local_tpm_handle;
if ((result = Tspi_Context_GetTpmObject(context_handle, &local_tpm_handle))) {
- LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_GetTpmObject";
return false;
}
@@ -456,7 +689,7 @@
TSS_HPOLICY tpm_usage_policy;
if ((result = Tspi_GetPolicyObject(local_tpm_handle, TSS_POLICY_USAGE,
&tpm_usage_policy))) {
- LOG(ERROR) << "Error calling Tspi_GetPolicyObject: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
return false;
}
@@ -464,7 +697,7 @@
owner_password.size(),
const_cast<BYTE *>(static_cast<const BYTE *>(
owner_password.const_data()))))) {
- LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
return false;
}
@@ -497,20 +730,25 @@
}
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 (!IsConnected()) {
- Connect();
- }
-
- if (!IsConnected()) {
- LOG(ERROR) << "Failed to connect to TPM";
+ if (is_disabled_) {
return false;
}
- if (is_disabled_) {
+ TSS_HCONTEXT context_handle = Connect();
+
+ if (!context_handle) {
+ LOG(ERROR) << "Failed to connect to TPM";
return false;
}
@@ -523,30 +761,39 @@
is_being_owned_ = true;
file_util::Delete(FilePath(kOpenCryptokiPath), true);
file_util::Delete(FilePath(kTpmOwnedFile), false);
+ file_util::Delete(FilePath(kTpmStatusFile), false);
- if (!IsEndorsementKeyAvailable(context_handle_)) {
- if (!CreateEndorsementKey(context_handle_)) {
+ if (!IsEndorsementKeyAvailable(context_handle)) {
+ if (!CreateEndorsementKey(context_handle)) {
LOG(ERROR) << "Failed to create endorsement key";
is_being_owned_ = false;
+ Disconnect(context_handle);
return false;
}
}
- if (!IsEndorsementKeyAvailable(context_handle_)) {
+ if (!IsEndorsementKeyAvailable(context_handle)) {
LOG(ERROR) << "Endorsement key is not available";
is_being_owned_ = false;
+ Disconnect(context_handle);
return false;
}
- if (!TakeOwnership(context_handle_, kMaxTimeoutRetries,
+ if (!TakeOwnership(context_handle, kMaxTimeoutRetries,
default_owner_password)) {
LOG(ERROR) << "Take Ownership failed";
is_being_owned_ = false;
+ Disconnect(context_handle);
return false;
}
is_owned_ = true;
took_ownership = true;
+
+ tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
+ TpmStatus::USES_WELL_KNOWN_OWNER);
+ tpm_status.clear_owner_password();
+ StoreTpmStatus(tpm_status);
}
if (OUT_took_ownership) {
@@ -557,11 +804,11 @@
TSS_RESULT result;
TSS_HKEY srk_handle;
TSS_UUID SRK_UUID = TSS_UUID_SRK;
- if ((result = Tspi_Context_LoadKeyByUUID(context_handle_, TSS_PS_TYPE_SYSTEM,
+ if ((result = Tspi_Context_LoadKeyByUUID(context_handle, TSS_PS_TYPE_SYSTEM,
SRK_UUID, &srk_handle))) {
is_srk_available_ = false;
} else {
- Tspi_Context_CloseObject(context_handle_, srk_handle);
+ Tspi_Context_CloseObject(context_handle, srk_handle);
is_srk_available_ = true;
}
@@ -569,38 +816,52 @@
// zero the SRK password and unrestrict it, then change the owner password.
TSS_HTPM tpm_handle;
if (!file_util::PathExists(FilePath(kTpmOwnedFile)) &&
- GetTpmWithAuth(context_handle_, default_owner_password, &tpm_handle) &&
+ GetTpmWithAuth(context_handle, default_owner_password, &tpm_handle) &&
TestTpmAuth(tpm_handle)) {
- if (!ZeroSrkPassword(context_handle_, default_owner_password)) {
+ if (!ZeroSrkPassword(context_handle, default_owner_password)) {
LOG(ERROR) << "Couldn't zero SRK password";
is_being_owned_ = false;
+ Disconnect(context_handle);
return false;
}
- if (!UnrestrictSrk(context_handle_, default_owner_password)) {
+ if (!UnrestrictSrk(context_handle, default_owner_password)) {
LOG(ERROR) << "Couldn't unrestrict the SRK";
is_being_owned_ = false;
+ Disconnect(context_handle);
return false;
}
+
SecureBlob owner_password;
CreateOwnerPassword(&owner_password);
- if (!ChangeOwnerPassword(context_handle_, default_owner_password,
- owner_password)) {
- LOG(ERROR) << "Couldn't set the owner password";
- is_being_owned_ = false;
- return false;
+ tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
+ TpmStatus::USES_RANDOM_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();
}
- password_sync_lock_.Acquire();
- owner_password_.assign(owner_password.begin(), owner_password.end());
- password_sync_lock_.Release();
-
file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0);
+ } 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 (!file_util::PathExists(FilePath(kTpmOwnedFile))) {
+ file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0);
+ }
}
is_being_owned_ = false;
-
+ Disconnect(context_handle);
return true;
}
@@ -622,7 +883,7 @@
SecureBlob random(length);
BYTE* tpm_data = NULL;
if ((result = Tspi_TPM_GetRandom(tpm_handle, random.size(), &tpm_data))) {
- LOG(ERROR) << "Could not get random data from the TPM: " << result;
+ TPM_LOG(ERROR, result) << "Could not get random data from the TPM";
Tspi_Context_Close(context_handle);
return false;
}
@@ -634,4 +895,124 @@
return true;
}
+bool Tpm::LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle,
+ TSS_RESULT* result) {
+ *result = TSS_SUCCESS;
+
+ // Load the Storage Root Key
+ TSS_UUID SRK_UUID = TSS_UUID_SRK;
+ TSS_HKEY local_srk_handle;
+ if ((*result = Tspi_Context_LoadKeyByUUID(context_handle,
+ TSS_PS_TYPE_SYSTEM,
+ SRK_UUID,
+ &local_srk_handle))) {
+ return false;
+ }
+
+ // Check if the SRK wants a password
+ UINT32 srk_authusage;
+ if ((*result = Tspi_GetAttribUint32(local_srk_handle,
+ TSS_TSPATTRIB_KEY_INFO,
+ TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
+ &srk_authusage))) {
+ Tspi_Context_CloseObject(context_handle,
+ local_srk_handle);
+ return false;
+ }
+
+ // Give it the password if needed
+ if (srk_authusage) {
+ TSS_HPOLICY srk_usage_policy;
+ if ((*result = Tspi_GetPolicyObject(local_srk_handle,
+ TSS_POLICY_USAGE,
+ &srk_usage_policy))) {
+ Tspi_Context_CloseObject(context_handle, local_srk_handle);
+ return false;
+ }
+
+ BYTE new_password[0];
+ if ((*result = Tspi_Policy_SetSecret(srk_usage_policy,
+ TSS_SECRET_MODE_PLAIN,
+ 0, new_password))) {
+ Tspi_Context_CloseObject(context_handle, local_srk_handle);
+ return false;
+ }
+ }
+
+ *srk_handle = local_srk_handle;
+ return true;
+}
+
+void Tpm::ClearStoredOwnerPassword() {
+ TpmStatus tpm_status;
+ if (LoadTpmStatus(&tpm_status)) {
+ 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::LoadTpmStatus(TpmStatus* serialized) {
+ FilePath tpm_status_file(kTpmStatusFile);
+ if (!file_util::PathExists(tpm_status_file)) {
+ return false;
+ }
+ SecureBlob file_data;
+ if (!LoadFileBytes(tpm_status_file, &file_data)) {
+ return 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);
+ FilePath tpm_status_file(kTpmStatusFile);
+ if (file_util::PathExists(tpm_status_file)) {
+ do {
+ int64 file_size;
+ if (!file_util::GetFileSize(tpm_status_file, &file_size)) {
+ break;
+ }
+ SecureBlob random;
+ if (!GetRandomData(file_size, &random)) {
+ break;
+ }
+ FILE* file = file_util::OpenFile(tpm_status_file, "wb+");
+ if (!file) {
+ break;
+ }
+ if (fwrite(random.const_data(), 1, random.size(), file) !=
+ random.size()) {
+ file_util::CloseFile(file);
+ break;
+ }
+ file_util::CloseFile(file);
+ } while(false);
+ file_util::Delete(tpm_status_file, false);
+ }
+ SecureBlob final_blob(serialized.ByteSize());
+ serialized.SerializeWithCachedSizesToArray(
+ static_cast<google::protobuf::uint8*>(final_blob.data()));
+ unsigned int data_written = file_util::WriteFile(
+ tpm_status_file,
+ static_cast<const char*>(final_blob.const_data()),
+ final_blob.size());
+
+ if (data_written != final_blob.size()) {
+ platform_->SetMask(old_mask);
+ return false;
+ }
+ platform_->SetMask(old_mask);
+ return true;
+}
+
} // namespace tpm_init
diff --git a/tpm.h b/tpm.h
index 27bec22..d209bbe 100644
--- a/tpm.h
+++ b/tpm.h
@@ -12,7 +12,9 @@
#include <trousers/trousers.h>
#include "crypto.h"
+#include "platform.h"
#include "secure_blob.h"
+#include "tpm_status.pb.h"
#ifndef TPM_INIT_TPM_H_
#define TPM_INIT_TPM_H_
@@ -32,15 +34,6 @@
// Parameters
virtual bool Init();
- // Tries to connect to the TPM
- virtual bool Connect();
-
- // Returns true if this instance is connected to the TPM
- virtual bool IsConnected();
-
- // Disconnects from the TPM
- virtual void Disconnect();
-
// Returns the number of simultaneously-loaded RSA keys that this TPM supports
int GetMaxRsaKeyCount();
@@ -51,6 +44,9 @@
// owner_password (OUT) - The random owner password used
bool GetOwnerPassword(chromeos::Blob* owner_password);
+ // Clears the owner password from storage
+ void ClearStoredOwnerPassword();
+
// 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).
@@ -79,6 +75,33 @@
bool GetRandomData(size_t length, chromeos::Blob* data);
private:
+ // Tries to connect to the TPM
+ virtual TSS_HCONTEXT Connect();
+
+ // Disconnects from the TPM
+ virtual void Disconnect(TSS_HCONTEXT context_handle);
+
+ // Gets a handle to the SRK
+ bool LoadSrk(TSS_HCONTEXT context_handle, TSS_HKEY* srk_handle,
+ TSS_RESULT* result);
+
+ // Loads the contents of the file specified into a blob
+ bool LoadFileBytes(const FilePath& path, chromeos::Blob* blob);
+
+ // 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);
+
// Attempts to connect to tcsd
//
// Parameters
@@ -116,6 +139,13 @@
// context_handle - The context handle for the TPM session
bool CreateEndorsementKey(TSS_HCONTEXT context_handle);
+ // Delegates ownership authority
+ //
+ // Parameters
+ // context_handle - The context handle for the TPM session
+ bool DelegateTpmOwnership(TSS_HCONTEXT context_handle, TSS_HTPM tpm_handle,
+ SecureBlob* delegation_blob);
+
// Checks to see if the endorsement key is available by attempting to get its
// public key
//
@@ -188,9 +218,6 @@
// tpm_handle = The TPM handle
bool TestTpmAuth(TSS_HTPM tpm_handle);
- // The context handle for this TPM session
- TSS_HCONTEXT context_handle_;
-
// The default Crypto instance to use (for generating the random owner
// password)
scoped_ptr<Crypto> default_crypto_;
@@ -198,6 +225,12 @@
// The actual Crypto instance to use
Crypto* crypto_;
+ // The default Platform instance to use
+ scoped_ptr<Platform> default_platform_;
+
+ // The actual Platform instance to use
+ Platform* platform_;
+
// If TPM ownership is taken, owner_password_ contains the password used
SecureBlob owner_password_;
diff --git a/tpm_init.cc b/tpm_init.cc
index ddd287a..3178790 100644
--- a/tpm_init.cc
+++ b/tpm_init.cc
@@ -7,6 +7,7 @@
#include "tpm_init.h"
#include <base/logging.h>
+#include <base/platform_thread.h>
#include <base/time.h>
#include "tpm.h"
@@ -17,33 +18,47 @@
// the TPM.
class TpmInitTask : public PlatformThread::Delegate {
public:
- TpmInitTask();
- virtual ~TpmInitTask();
+ TpmInitTask()
+ : default_tpm_(new tpm_init::Tpm()),
+ tpm_(default_tpm_.get()),
+ init_(NULL) {
+ }
- void Init(TpmInit::TpmInitCallback* notify_callback);
+ virtual ~TpmInitTask() {
+ }
- virtual void ThreadMain();
+ void Init(TpmInit* init) {
+ init_ = init;
+ tpm_->Init();
+ }
- bool IsTpmReady();
- bool IsTpmEnabled();
- bool IsTpmOwned();
- bool IsTpmBeingOwned();
- bool GetTpmPassword(chromeos::Blob* password);
- long GetInitializationMillis();
- bool GetRandomData(int length, chromeos::Blob* data);
+ virtual void ThreadMain() {
+ if (init_) {
+ init_->ThreadMain();
+ }
+ }
+
+ void set_tpm(tpm_init::Tpm* tpm) {
+ tpm_ = tpm;
+ }
+
+ tpm_init::Tpm* get_tpm() {
+ return tpm_;
+ }
private:
scoped_ptr<tpm_init::Tpm> default_tpm_;
tpm_init::Tpm* tpm_;
- bool initialize_took_ownership_;
- bool task_done_;
- long initialization_time_;
- TpmInit::TpmInitCallback* notify_callback_;
+ TpmInit* init_;
};
TpmInit::TpmInit()
: tpm_init_task_(new TpmInitTask()),
- notify_callback_(NULL) {
+ notify_callback_(NULL),
+ initialize_called_(false),
+ task_done_(false),
+ initialize_took_ownership_(false),
+ initialization_time_(0) {
}
TpmInit::~TpmInit() {
@@ -51,14 +66,15 @@
void TpmInit::Init(TpmInitCallback* notify_callback) {
notify_callback_ = notify_callback;
+ tpm_init_task_->Init(this);
}
bool TpmInit::GetRandomData(int length, chromeos::Blob* data) {
- return tpm_init_task_->GetRandomData(length, data);
+ return tpm_init_task_->get_tpm()->GetRandomData(length, data);
}
bool TpmInit::StartInitializeTpm() {
- tpm_init_task_->Init(notify_callback_);
+ initialize_called_ = true;
if (!PlatformThread::CreateNonJoinable(0, tpm_init_task_.get())) {
LOG(ERROR) << "Unable to create TPM initialization background thread.";
return false;
@@ -67,62 +83,6 @@
}
bool TpmInit::IsTpmReady() {
- return tpm_init_task_->IsTpmReady();
-}
-
-bool TpmInit::IsTpmEnabled() {
- return tpm_init_task_->IsTpmEnabled();
-}
-
-bool TpmInit::IsTpmOwned() {
- return tpm_init_task_->IsTpmOwned();
-}
-
-bool TpmInit::IsTpmBeingOwned() {
- return tpm_init_task_->IsTpmBeingOwned();
-}
-
-bool TpmInit::GetTpmPassword(chromeos::Blob* password) {
- return tpm_init_task_->GetTpmPassword(password);
-}
-
-long TpmInit::GetInitializationMillis() {
- return tpm_init_task_->GetInitializationMillis();
-}
-
-TpmInitTask::TpmInitTask()
- : default_tpm_(new tpm_init::Tpm()),
- tpm_(default_tpm_.get()),
- initialize_took_ownership_(false),
- task_done_(false),
- initialization_time_(-1),
- notify_callback_(NULL) {
-}
-
-TpmInitTask::~TpmInitTask() {
-}
-
-void TpmInitTask::Init(TpmInit::TpmInitCallback* notify_callback) {
- notify_callback_ = notify_callback;
- tpm_->Init();
-}
-
-void TpmInitTask::ThreadMain() {
- base::TimeTicks start = base::TimeTicks::Now();
- bool initialize_result = tpm_->InitializeTpm(&initialize_took_ownership_);
- base::TimeDelta delta = (base::TimeTicks::Now() - start);
- initialization_time_ = delta.InMilliseconds();
- if (initialize_took_ownership_) {
- LOG(ERROR) << "TPM initialization took " << initialization_time_ << "ms";
- }
- task_done_ = true;
- if (notify_callback_) {
- notify_callback_->InitializeTpmComplete(initialize_result,
- initialize_took_ownership_);
- }
-}
-
-bool TpmInitTask::IsTpmReady() {
// The TPM is not "ready" if the init call has not completed. It may be in
// the middle of taking ownership.
if (!task_done_) {
@@ -137,31 +97,52 @@
// returned false. That merely means that it did not successfully take
// ownership, which is the common case after ownership is established on OOBE.
// In that case, the TPM is ready if it is enabled and owned.
- return (tpm_->IsEnabled() && tpm_->IsOwned());
+ return (tpm_init_task_->get_tpm()->IsEnabled() &&
+ tpm_init_task_->get_tpm()->IsOwned());
}
-bool TpmInitTask::IsTpmEnabled() {
- return tpm_->IsEnabled();
+bool TpmInit::IsTpmEnabled() {
+ return tpm_init_task_->get_tpm()->IsEnabled();
}
-bool TpmInitTask::IsTpmOwned() {
- return tpm_->IsOwned();
+bool TpmInit::IsTpmOwned() {
+ return tpm_init_task_->get_tpm()->IsOwned();
}
-bool TpmInitTask::IsTpmBeingOwned() {
- return tpm_->IsBeingOwned();
+bool TpmInit::IsTpmBeingOwned() {
+ return tpm_init_task_->get_tpm()->IsBeingOwned();
}
-bool TpmInitTask::GetTpmPassword(chromeos::Blob* password) {
- return tpm_->GetOwnerPassword(password);
+bool TpmInit::HasInitializeBeenCalled() {
+ return initialize_called_;
}
-long TpmInitTask::GetInitializationMillis() {
+bool TpmInit::GetTpmPassword(chromeos::Blob* password) {
+ return tpm_init_task_->get_tpm()->GetOwnerPassword(password);
+}
+
+void TpmInit::ClearStoredTpmPassword() {
+ tpm_init_task_->get_tpm()->ClearStoredOwnerPassword();
+}
+
+long TpmInit::GetInitializationMillis() {
return initialization_time_;
}
-bool TpmInitTask::GetRandomData(int length, chromeos::Blob* data) {
- return tpm_->GetRandomData(length, data);
+void TpmInit::ThreadMain() {
+ base::TimeTicks start = base::TimeTicks::Now();
+ bool initialize_result = tpm_init_task_->get_tpm()->InitializeTpm(
+ &initialize_took_ownership_);
+ base::TimeDelta delta = (base::TimeTicks::Now() - start);
+ initialization_time_ = delta.InMilliseconds();
+ if (initialize_took_ownership_) {
+ LOG(ERROR) << "TPM initialization took " << initialization_time_ << "ms";
+ }
+ task_done_ = true;
+ if (notify_callback_) {
+ notify_callback_->InitializeTpmComplete(initialize_result,
+ initialize_took_ownership_);
+ }
}
} // namespace tpm_init
diff --git a/tpm_init.h b/tpm_init.h
index 8a0024f..5cb00c7 100644
--- a/tpm_init.h
+++ b/tpm_init.h
@@ -4,8 +4,8 @@
// TpmInit - public interface class for initializing the TPM
+#include <base/basictypes.h>
#include <base/scoped_ptr.h>
-#include <base/platform_thread.h>
#include <chromeos/utility.h>
#ifndef TPM_INIT_TPM_INIT_H_
@@ -16,6 +16,10 @@
class TpmInitTask;
class TpmInit {
+ // Friend class TpmInitTask as it is a glue class to allow ThreadMain to be
+ // called on a separate thread without inheriting from
+ // PlatformThread::Delegate
+ friend class TpmInitTask;
public:
class TpmInitCallback {
@@ -52,22 +56,35 @@
// Returns true if the TPM is being owned
virtual bool IsTpmBeingOwned();
+ // Returns true if initialization has been called
+ virtual bool HasInitializeBeenCalled();
+
// Gets the TPM password if the TPM initialization took ownership
//
// Parameters
// password (OUT) - The owner password used for the TPM
virtual bool GetTpmPassword(chromeos::Blob* password);
+ // Clears the TPM password from memory and disk
+ virtual void ClearStoredTpmPassword();
+
// Returns the number of milliseconds it took to initialize the TPM
virtual long GetInitializationMillis();
private:
+ virtual void ThreadMain();
+
// The background task for initializing the TPM, implemented as a
// PlatformThread::Delegate
scoped_ptr<TpmInitTask> tpm_init_task_;
TpmInitCallback* notify_callback_;
+ bool initialize_called_;
+ bool task_done_;
+ bool initialize_took_ownership_;
+ long initialization_time_;
+
DISALLOW_COPY_AND_ASSIGN(TpmInit);
};
diff --git a/tpm_status.proto b/tpm_status.proto
new file mode 100644
index 0000000..273faa2
--- /dev/null
+++ b/tpm_status.proto
@@ -0,0 +1,17 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package tpm_init;
+
+message TpmStatus {
+ enum Flags {
+ NONE = 0;
+ OWNED_BY_THIS_INSTALL = 1;
+ USES_WELL_KNOWN_OWNER = 2;
+ USES_RANDOM_OWNER = 4;
+ }
+ required int32 flags = 1;
+ optional bytes delegation_credentials = 2;
+ optional bytes owner_password = 3;
+}