Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Unified Diff: tpm.cc

Issue 3475009: Adds the necessary changes to tpm_init to allow triggered initialization. (Closed) Base URL: http://git.chromium.org/git/tpm_init.git
Patch Set: Address feedback. Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tpm.h ('k') | tpm_init.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tpm.cc
diff --git a/tpm.cc b/tpm.cc
index 1efa15c57d68bac73148e49045d460883b01933a..1f7d75c81581478d3da4522a3e9dec23583eb342 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 int kMaxTimeoutRetries = 5;
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()
}
Tpm::~Tpm() {
- Disconnect();
}
bool Tpm::Init() {
@@ -49,9 +56,11 @@ bool Tpm::Init() {
// 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,42 +70,75 @@ bool Tpm::Init() {
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;
}
+ int count = GetMaxRsaKeyCountForContext(context_handle);
+ Disconnect(context_handle);
+ return count;
+}
+
+bool Tpm::IsDisabledCheckViaSysfs() {
+ std::string contents;
+ if (!file_util::ReadFileToString(FilePath(kTpmCheckEnabledFile), &contents)) {
+ return false;
+ }
+ if (contents.size() < 1) {
+ return false;
+ }
+ return (contents[0] == '0');
+}
- return GetMaxRsaKeyCountForContext(context_handle_);
+bool Tpm::IsOwnedCheckViaSysfs() {
+ std::string contents;
+ if (!file_util::ReadFileToString(FilePath(kTpmCheckOwnedFile), &contents)) {
+ return false;
+ }
+ if (contents.size() < 1) {
+ return false;
+ }
+ return (contents[0] != '0');
}
int Tpm::GetMaxRsaKeyCountForContext(TSS_HCONTEXT context_handle) {
@@ -114,7 +156,7 @@ int Tpm::GetMaxRsaKeyCountForContext(TSS_HCONTEXT context_handle) {
sizeof(subcap),
reinterpret_cast<BYTE*>(&subcap),
&cap_length, &cap))) {
- LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
return count;
}
if (cap_length == sizeof(int)) {
@@ -128,7 +170,7 @@ 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";
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Create";
return false;
}
@@ -137,7 +179,7 @@ bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
if (result == TSS_E_COMM_FAILURE) {
PlatformThread::Sleep(kTpmConnectIntervalMs);
} else {
- LOG(ERROR) << "Error calling Tspi_Context_Connect: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Connect";
Tspi_Context_Close(local_context_handle);
return false;
}
@@ -147,7 +189,7 @@ bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
}
if (result) {
- LOG(ERROR) << "Error calling Tspi_Context_Connect: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_Context_Connect";
Tspi_Context_Close(local_context_handle);
return false;
}
@@ -156,28 +198,6 @@ bool Tpm::OpenAndConnectTpm(TSS_HCONTEXT* context_handle) {
return true;
}
-bool Tpm::IsDisabledCheckViaSysfs() {
- std::string contents;
- if (!file_util::ReadFileToString(FilePath(kTpmCheckEnabledFile), &contents)) {
- return false;
- }
- if (contents.size() < 1) {
- return false;
- }
- return (contents[0] == '0');
-}
-
-bool Tpm::IsOwnedCheckViaSysfs() {
- std::string contents;
- if (!file_util::ReadFileToString(FilePath(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;
@@ -218,13 +238,13 @@ bool Tpm::CreateEndorsementKey(TSS_HCONTEXT context_handle) {
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 @@ bool Tpm::IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle) {
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 @@ bool Tpm::IsEndorsementKeyAvailable(TSS_HCONTEXT context_handle) {
}
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 @@ bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries,
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 @@ bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries,
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 @@ bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries,
(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 @@ bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
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::ZeroSrkPassword(TSS_HCONTEXT context_handle,
}
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 @@ bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle,
if ((result = Tspi_TPM_GetStatus(tpm_handle,
TSS_TPMSTATUS_DISABLEPUBSRKREAD,
&current_status))) {
- LOG(ERROR) << "Error calling Tspi_TPM_GetStatus: " << result;
+ TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetStatus";
return false;
}
@@ -387,7 +409,7 @@ bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::ChangeOwnerPassword(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::ChangeOwnerPassword(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::GetTpm(TSS_HCONTEXT context_handle, TSS_HTPM* tpm_handle) {
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 @@ bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle,
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 @@ bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle,
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::GetOwnerPassword(chromeos::Blob* owner_password) {
}
bool Tpm::InitializeTpm(bool* OUT_took_ownership) {
- if (OUT_took_ownership) {
- *OUT_took_ownership = false;
+ TpmStatus tpm_status;
+
+ if (!LoadTpmStatus(&tpm_status)) {
+ tpm_status.Clear();
+ tpm_status.set_flags(TpmStatus::NONE);
}
- if (!IsConnected()) {
- Connect();
+ if (OUT_took_ownership) {
+ *OUT_took_ownership = false;
}
- 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 @@ bool Tpm::InitializeTpm(bool* OUT_took_ownership) {
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 @@ bool Tpm::InitializeTpm(bool* OUT_took_ownership) {
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 @@ bool Tpm::InitializeTpm(bool* OUT_took_ownership) {
// 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);
- password_sync_lock_.Acquire();
- owner_password_.assign(owner_password.begin(), owner_password.end());
- password_sync_lock_.Release();
+ 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();
+ }
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 @@ bool Tpm::GetRandomData(size_t length, chromeos::Blob* data) {
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 @@ bool Tpm::GetRandomData(size_t length, chromeos::Blob* data) {
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
« no previous file with comments | « tpm.h ('k') | tpm_init.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698