| Index: tpm.cc
|
| diff --git a/tpm.cc b/tpm.cc
|
| index 37c5ab71cb4ebfd4bfbb1ef70bdc89b60599a5c5..b18514596f24f6d7b7ddc10d06d5667b8cb5ead1 100644
|
| --- a/tpm.cc
|
| +++ b/tpm.cc
|
| @@ -24,6 +24,7 @@ const char* kTpmOwnedFile = "/var/lib/.tpm_owned";
|
| const char* kOpenCryptokiPath = "/var/lib/opencryptoki";
|
| const int kTpmConnectRetries = 10;
|
| const int kTpmConnectIntervalMs = 100;
|
| +const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET;
|
|
|
| Tpm::Tpm()
|
| : context_handle_(0),
|
| @@ -32,7 +33,8 @@ Tpm::Tpm()
|
| owner_password_(),
|
| password_sync_lock_(),
|
| is_disabled_(true),
|
| - is_owned_(false) {
|
| + is_owned_(false),
|
| + is_srk_available_(false) {
|
| }
|
|
|
| Tpm::~Tpm() {
|
| @@ -49,6 +51,17 @@ bool Tpm::Init() {
|
| if (file_util::PathExists(FilePath(kTpmCheckEnabledFile))) {
|
| is_disabled_ = IsDisabledCheckViaSysfs();
|
| is_owned_ = IsOwnedCheckViaSysfs();
|
| + } else {
|
| + TSS_HCONTEXT context_handle;
|
| + if (OpenAndConnectTpm(&context_handle)) {
|
| + bool enabled = false;
|
| + bool owned = false;
|
| + IsEnabledOwnedCheckViaContext(context_handle, &enabled, &owned);
|
| + is_disabled_ = !enabled;
|
| + is_owned_ = owned;
|
| + Tspi_Context_Close(context_handle);
|
| + } else {
|
| + }
|
| }
|
| return true;
|
| }
|
| @@ -164,49 +177,32 @@ bool Tpm::IsOwnedCheckViaSysfs() {
|
| return (contents[0] != '0');
|
| }
|
|
|
| -bool Tpm::IsDisabledCheckViaContext(TSS_HCONTEXT context_handle) {
|
| - bool value = true;
|
| - TSS_RESULT result;
|
| - TSS_HTPM tpm_handle;
|
| - if (!GetTpm(context_handle, &tpm_handle)) {
|
| - return value;
|
| - }
|
| +void Tpm::IsEnabledOwnedCheckViaContext(TSS_HCONTEXT context_handle,
|
| + bool* enabled, bool* owned) {
|
| + *enabled = false;
|
| + *owned = false;
|
|
|
| - UINT32 cap_length = 0;
|
| - BYTE* cap = NULL;
|
| - if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_FLAG,
|
| - 0, NULL, &cap_length, &cap))) {
|
| - LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result;
|
| - return value;
|
| - }
|
| - if (cap_length >= (2 * sizeof(int))) {
|
| - value = (((*(reinterpret_cast<int*>(cap))) & TPM_PF_DISABLE) != 0);
|
| - }
|
| - Tspi_Context_FreeMemory(context_handle, cap);
|
| - return value;
|
| -}
|
| -
|
| -bool Tpm::IsOwnedCheckViaContext(TSS_HCONTEXT context_handle) {
|
| - bool value = true;
|
| TSS_RESULT result;
|
| TSS_HTPM tpm_handle;
|
| if (!GetTpm(context_handle, &tpm_handle)) {
|
| - LOG(ERROR) << "Error calling Tspi_Context_GetTpmObject: " << result;
|
| - return value;
|
| + return;
|
| }
|
|
|
| + UINT32 sub_cap = TSS_TPMCAP_PROP_OWNER;
|
| UINT32 cap_length = 0;
|
| BYTE* cap = NULL;
|
| - if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_FLAG,
|
| - 0, NULL, &cap_length, &cap))) {
|
| - LOG(ERROR) << "Error calling Tspi_TPM_GetCapability: " << result;
|
| - return value;
|
| - }
|
| - if (cap_length >= (2 * sizeof(int))) {
|
| - value = (((*(reinterpret_cast<int*>(cap))) & TPM_PF_OWNERSHIP) != 0);
|
| + if ((result = Tspi_TPM_GetCapability(tpm_handle, TSS_TPMCAP_PROPERTY,
|
| + sizeof(sub_cap),
|
| + reinterpret_cast<BYTE*>(&sub_cap),
|
| + &cap_length, &cap)) == 0) {
|
| + if (cap_length >= (sizeof(TSS_BOOL))) {
|
| + *enabled = true;
|
| + *owned = ((*(reinterpret_cast<TSS_BOOL*>(cap))) != 0);
|
| + }
|
| + Tspi_Context_FreeMemory(context_handle, cap);
|
| + } else if(ERROR_CODE(result) == TPM_E_DISABLED) {
|
| + *enabled = false;
|
| }
|
| - Tspi_Context_FreeMemory(context_handle, cap);
|
| - return value;
|
| }
|
|
|
| bool Tpm::CreateEndorsementKey(TSS_HCONTEXT context_handle) {
|
| @@ -245,7 +241,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_Context_CreateObject: " << result;
|
| + LOG(ERROR) << "Error calling Tspi_TPM_GetPubEndorsementKey: " << result;
|
| return false;
|
| }
|
|
|
| @@ -264,10 +260,8 @@ void Tpm::CreateOwnerPassword(SecureBlob* password) {
|
| password->swap(tpm_password);
|
| }
|
|
|
| -bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries) {
|
| - SecureBlob owner_password;
|
| - CreateOwnerPassword(&owner_password);
|
| -
|
| +bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries,
|
| + const SecureBlob& owner_password) {
|
| TSS_RESULT result;
|
| TSS_HTPM tpm_handle;
|
| if (!GetTpmWithAuth(context_handle, owner_password, &tpm_handle)) {
|
| @@ -318,10 +312,6 @@ bool Tpm::TakeOwnership(TSS_HCONTEXT context_handle, int max_timeout_tries) {
|
|
|
| Tspi_Context_CloseObject(context_handle, srk_handle);
|
|
|
| - password_sync_lock_.Acquire();
|
| - owner_password_.swap(owner_password);
|
| - password_sync_lock_.Release();
|
| -
|
| return true;
|
| }
|
|
|
| @@ -337,7 +327,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) << "Couldn't load SRK: " << result;
|
| + LOG(ERROR) << "Error calling Tspi_Context_LoadKeyByUUID: " << result;
|
| return false;
|
| }
|
|
|
| @@ -346,7 +336,7 @@ bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
|
| TSS_OBJECT_TYPE_POLICY,
|
| TSS_POLICY_USAGE,
|
| &policy_handle))) {
|
| - LOG(ERROR) << "Error creating policy object: " << result;
|
| + LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result;
|
| Tspi_Context_CloseObject(context_handle, srk_handle);
|
| return false;
|
| }
|
| @@ -354,7 +344,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 setting srk password: " << result;
|
| + LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result;
|
| Tspi_Context_CloseObject(context_handle, policy_handle);
|
| Tspi_Context_CloseObject(context_handle, srk_handle);
|
| return false;
|
| @@ -363,7 +353,7 @@ bool Tpm::ZeroSrkPassword(TSS_HCONTEXT context_handle,
|
| if ((result = Tspi_ChangeAuth(srk_handle,
|
| tpm_handle,
|
| policy_handle))) {
|
| - LOG(ERROR) << "Error creating policy object: " << result;
|
| + LOG(ERROR) << "Error calling Tspi_ChangeAuth: " << result;
|
| Tspi_Context_CloseObject(context_handle, policy_handle);
|
| Tspi_Context_CloseObject(context_handle, srk_handle);
|
| return false;
|
| @@ -382,10 +372,59 @@ bool Tpm::UnrestrictSrk(TSS_HCONTEXT context_handle,
|
| return false;
|
| }
|
|
|
| - if ((result = Tspi_TPM_SetStatus(tpm_handle,
|
| + TSS_BOOL current_status = false;
|
| +
|
| + if ((result = Tspi_TPM_GetStatus(tpm_handle,
|
| TSS_TPMSTATUS_DISABLEPUBSRKREAD,
|
| - false))) {
|
| - LOG(ERROR) << "Error calling Tspi_TPM_SetStatus: " << result;
|
| + ¤t_status))) {
|
| + LOG(ERROR) << "Error calling Tspi_TPM_GetStatus: " << result;
|
| + return false;
|
| + }
|
| +
|
| + // If it is currently owner auth (true), set it to SRK auth
|
| + if (current_status) {
|
| + if ((result = Tspi_TPM_SetStatus(tpm_handle,
|
| + TSS_TPMSTATUS_DISABLEPUBSRKREAD,
|
| + false))) {
|
| + LOG(ERROR) << "Error calling Tspi_TPM_SetStatus: " << result;
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool Tpm::ChangeOwnerPassword(TSS_HCONTEXT context_handle,
|
| + const SecureBlob& previous_owner_password,
|
| + const SecureBlob& owner_password) {
|
| + TSS_RESULT result;
|
| + TSS_HTPM tpm_handle;
|
| + if (!GetTpmWithAuth(context_handle, previous_owner_password, &tpm_handle)) {
|
| + return false;
|
| + }
|
| +
|
| + TSS_HPOLICY policy_handle;
|
| + if ((result = Tspi_Context_CreateObject(context_handle,
|
| + TSS_OBJECT_TYPE_POLICY,
|
| + TSS_POLICY_USAGE,
|
| + &policy_handle))) {
|
| + LOG(ERROR) << "Error calling Tspi_Context_CreateObject: " << result;
|
| + return false;
|
| + }
|
| +
|
| + if ((result = Tspi_Policy_SetSecret(policy_handle,
|
| + TSS_SECRET_MODE_PLAIN,
|
| + owner_password.size(),
|
| + const_cast<BYTE *>(static_cast<const BYTE *>(
|
| + owner_password.const_data()))))) {
|
| + LOG(ERROR) << "Error calling Tspi_Policy_SetSecret: " << result;
|
| + 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;
|
| + Tspi_Context_CloseObject(context_handle, policy_handle);
|
| return false;
|
| }
|
|
|
| @@ -410,7 +449,6 @@ bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle,
|
| TSS_RESULT result;
|
| TSS_HTPM local_tpm_handle;
|
| if (!GetTpm(context_handle, &local_tpm_handle)) {
|
| - LOG(ERROR) << "Error getting TPM handle";
|
| return false;
|
| }
|
|
|
| @@ -433,6 +471,18 @@ bool Tpm::GetTpmWithAuth(TSS_HCONTEXT context_handle,
|
| return true;
|
| }
|
|
|
| +bool Tpm::TestTpmAuth(TSS_HTPM tpm_handle) {
|
| + // Call Tspi_TPM_GetStatus to test the authentication
|
| + TSS_RESULT result;
|
| + TSS_BOOL current_status = false;
|
| + if ((result = Tspi_TPM_GetStatus(tpm_handle,
|
| + TSS_TPMSTATUS_DISABLED,
|
| + ¤t_status))) {
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| bool Tpm::GetOwnerPassword(chromeos::Blob* owner_password) {
|
| bool result = false;
|
| if (password_sync_lock_.Try()) {
|
| @@ -459,50 +509,79 @@ bool Tpm::InitializeTpm() {
|
| return false;
|
| }
|
|
|
| - if (is_owned_) {
|
| - return false;
|
| - }
|
| + SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
|
| + memcpy(default_owner_password.data(), kTpmWellKnownPassword,
|
| + sizeof(kTpmWellKnownPassword));
|
| +
|
| + bool took_ownership = false;
|
| + if (!is_owned_) {
|
| + file_util::Delete(FilePath(kOpenCryptokiPath), true);
|
| + file_util::Delete(FilePath(kTpmOwnedFile), false);
|
| +
|
| + if (!IsEndorsementKeyAvailable(context_handle_)) {
|
| + if (!CreateEndorsementKey(context_handle_)) {
|
| + LOG(ERROR) << "Failed to create endorsement key";
|
| + return false;
|
| + }
|
| + }
|
|
|
| - file_util::Delete(FilePath(kOpenCryptokiPath), true);
|
| - file_util::Delete(FilePath(kTpmOwnedFile), false);
|
| + if (!IsEndorsementKeyAvailable(context_handle_)) {
|
| + LOG(ERROR) << "Endorsement key is not available";
|
| + return false;
|
| + }
|
|
|
| - if (!IsEndorsementKeyAvailable(context_handle_)) {
|
| - if (!CreateEndorsementKey(context_handle_)) {
|
| - LOG(ERROR) << "Failed to create endorsement key";
|
| + if (!TakeOwnership(context_handle_, kMaxTimeoutRetries,
|
| + default_owner_password)) {
|
| + LOG(ERROR) << "Take Ownership failed";
|
| return false;
|
| }
|
| - }
|
|
|
| - if (!IsEndorsementKeyAvailable(context_handle_)) {
|
| - LOG(ERROR) << "Endorsement key is not available";
|
| - return false;
|
| + is_owned_ = true;
|
| + took_ownership = true;
|
| }
|
|
|
| - if (!TakeOwnership(context_handle_, kMaxTimeoutRetries)) {
|
| - LOG(ERROR) << "Take Ownership failed";
|
| - return false;
|
| + // Ensure the SRK is available
|
| + TSS_HKEY srk_handle;
|
| + TSS_UUID SRK_UUID = TSS_UUID_SRK;
|
| + 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);
|
| + is_srk_available_ = true;
|
| }
|
|
|
| - SecureBlob owner_password;
|
| - password_sync_lock_.Acquire();
|
| - owner_password.assign(owner_password_.begin(), owner_password_.end());
|
| - password_sync_lock_.Release();
|
| + // 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 (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";
|
| + return false;
|
| + }
|
|
|
| - if (!ZeroSrkPassword(context_handle_, owner_password)) {
|
| - LOG(ERROR) << "Couldn't zero SRK password";
|
| - return false;
|
| - }
|
| + if (!UnrestrictSrk(context_handle_, default_owner_password)) {
|
| + LOG(ERROR) << "Couldn't unrestrict the SRK";
|
| + return false;
|
| + }
|
| + SecureBlob owner_password;
|
| + CreateOwnerPassword(&owner_password);
|
|
|
| - if (!UnrestrictSrk(context_handle_, owner_password)) {
|
| - LOG(ERROR) << "Couldn't unrestrict the SRK";
|
| - return false;
|
| - }
|
| + if (!ChangeOwnerPassword(context_handle_, default_owner_password,
|
| + owner_password)) {
|
| + LOG(ERROR) << "Couldn't set the owner password";
|
| + return false;
|
| + }
|
|
|
| - is_owned_ = true;
|
| + password_sync_lock_.Acquire();
|
| + owner_password_.assign(owner_password.begin(), owner_password.end());
|
| + password_sync_lock_.Release();
|
|
|
| - file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0);
|
| + file_util::WriteFile(FilePath(kTpmOwnedFile), NULL, 0);
|
| + }
|
|
|
| - return true;
|
| + return took_ownership;
|
| }
|
|
|
| } // namespace tpm_init
|
|
|