| // |
| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "tpm_manager/server/tpm2_nvram_impl.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include <base/logging.h> |
| #include <trunks/error_codes.h> |
| #include <trunks/policy_session.h> |
| #include <trunks/tpm_constants.h> |
| #include <trunks/tpm_utility.h> |
| |
| namespace tpm_manager { |
| |
| using trunks::GetErrorString; |
| using trunks::TPM_RC; |
| using trunks::TPM_RC_SUCCESS; |
| |
| namespace { |
| |
| void MapAttributesFromTpm(trunks::TPMA_NV tpm_flags, |
| std::vector<NvramSpaceAttribute>* attributes) { |
| if (tpm_flags & trunks::TPMA_NV_WRITEDEFINE) |
| attributes->push_back(NVRAM_PERSISTENT_WRITE_LOCK); |
| if (tpm_flags & trunks::TPMA_NV_WRITE_STCLEAR) |
| attributes->push_back(NVRAM_BOOT_WRITE_LOCK); |
| if (tpm_flags & trunks::TPMA_NV_READ_STCLEAR) |
| attributes->push_back(NVRAM_BOOT_READ_LOCK); |
| if (tpm_flags & (trunks::TPMA_NV_AUTHWRITE)) |
| attributes->push_back(NVRAM_WRITE_AUTHORIZATION); |
| if (tpm_flags & (trunks::TPMA_NV_AUTHREAD)) |
| attributes->push_back(NVRAM_READ_AUTHORIZATION); |
| if (tpm_flags & trunks::TPMA_NV_GLOBALLOCK) |
| attributes->push_back(NVRAM_GLOBAL_LOCK); |
| if (tpm_flags & trunks::TPMA_NV_PPWRITE) |
| attributes->push_back(NVRAM_PLATFORM_WRITE); |
| if (tpm_flags & trunks::TPMA_NV_OWNERWRITE) |
| attributes->push_back(NVRAM_OWNER_WRITE); |
| if (tpm_flags & trunks::TPMA_NV_OWNERREAD) |
| attributes->push_back(NVRAM_OWNER_READ); |
| if (tpm_flags & trunks::TPMA_NV_EXTEND) |
| attributes->push_back(NVRAM_WRITE_EXTEND); |
| } |
| |
| bool MapAttributesToTpm( |
| const std::vector<NvramSpaceAttribute>& attributes, |
| trunks::TPMA_NV* tpm_flags, |
| bool* world_read_allowed, |
| bool* world_write_allowed) { |
| // Always require policy, even if it's an empty policy. |
| *tpm_flags = trunks::TPMA_NV_POLICYWRITE | trunks::TPMA_NV_POLICYREAD; |
| *world_read_allowed = true; |
| *world_write_allowed = true; |
| for (auto attribute : attributes) { |
| switch (attribute) { |
| case NVRAM_PERSISTENT_WRITE_LOCK: |
| *tpm_flags |= trunks::TPMA_NV_WRITEDEFINE; |
| break; |
| case NVRAM_BOOT_WRITE_LOCK: |
| *tpm_flags |= trunks::TPMA_NV_WRITE_STCLEAR; |
| break; |
| case NVRAM_BOOT_READ_LOCK: |
| *tpm_flags |= trunks::TPMA_NV_READ_STCLEAR; |
| break; |
| case NVRAM_WRITE_AUTHORIZATION: |
| *world_write_allowed = false; |
| break; |
| case NVRAM_READ_AUTHORIZATION: |
| *world_read_allowed = false; |
| break; |
| case NVRAM_WRITE_EXTEND: |
| *tpm_flags |= trunks::TPMA_NV_EXTEND; |
| break; |
| case NVRAM_GLOBAL_LOCK: |
| case NVRAM_PLATFORM_WRITE: |
| case NVRAM_OWNER_WRITE: |
| case NVRAM_OWNER_READ: |
| return false; |
| default: |
| break; |
| } |
| } |
| return true; |
| } |
| |
| NvramResult MapTpmError(TPM_RC tpm_error) { |
| switch (trunks::GetFormatOneError(tpm_error)) { |
| case trunks::TPM_RC_SUCCESS: |
| return NVRAM_RESULT_SUCCESS; |
| case trunks::TPM_RC_NV_RANGE: |
| case trunks::TPM_RC_NV_SIZE: |
| case trunks::TPM_RC_ATTRIBUTES: |
| return NVRAM_RESULT_INVALID_PARAMETER; |
| case trunks::TPM_RC_NV_LOCKED: |
| case trunks::TPM_RC_NV_UNINITIALIZED: |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| case trunks::TPM_RC_NV_AUTHORIZATION: |
| case trunks::TPM_RC_BAD_AUTH: |
| case trunks::TPM_RC_AUTH_FAIL: |
| case trunks::TPM_RC_POLICY_FAIL: |
| return NVRAM_RESULT_ACCESS_DENIED; |
| case trunks::TPM_RC_NV_SPACE: |
| return NVRAM_RESULT_INSUFFICIENT_SPACE; |
| case trunks::TPM_RC_NV_DEFINED: |
| return NVRAM_RESULT_SPACE_ALREADY_EXISTS; |
| case trunks::TPM_RC_HANDLE: |
| return NVRAM_RESULT_SPACE_DOES_NOT_EXIST; |
| } |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| |
| } // namespace |
| |
| Tpm2NvramImpl::Tpm2NvramImpl(const trunks::TrunksFactory& factory, |
| LocalDataStore* local_data_store) |
| : trunks_factory_(factory), |
| local_data_store_(local_data_store), |
| initialized_(false), |
| trunks_session_(trunks_factory_.GetHmacSession()), |
| trunks_utility_(trunks_factory_.GetTpmUtility()) {} |
| |
| NvramResult Tpm2NvramImpl::DefineSpace( |
| uint32_t index, |
| size_t size, |
| const std::vector<NvramSpaceAttribute>& attributes, |
| const std::string& authorization_value, |
| NvramSpacePolicy policy) { |
| if (!Initialize()) { |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| if (!SetupOwnerSession()) { |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| trunks::TPMA_NV attribute_flags = 0; |
| bool world_read_allowed = false; |
| bool world_write_allowed = false; |
| if (!MapAttributesToTpm(attributes, &attribute_flags, &world_read_allowed, |
| &world_write_allowed)) { |
| return NVRAM_RESULT_INVALID_PARAMETER; |
| } |
| NvramPolicyRecord policy_record; |
| policy_record.set_index(index); |
| policy_record.set_policy(policy); |
| policy_record.set_world_read_allowed(world_read_allowed); |
| policy_record.set_world_write_allowed(world_write_allowed); |
| std::string policy_digest; |
| if (!ComputePolicyDigest(&policy_record, &policy_digest)) { |
| LOG(ERROR) << "Failed to compute policy digest."; |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| TPM_RC result = trunks_utility_->DefineNVSpace( |
| index, size, attribute_flags, authorization_value, policy_digest, |
| trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error defining nvram space: " << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| if (!SavePolicyRecord(policy_record)) { |
| trunks_utility_->DestroyNVSpace(index, trunks_session_->GetDelegate()); |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| return NVRAM_RESULT_SUCCESS; |
| } |
| |
| NvramResult Tpm2NvramImpl::DestroySpace(uint32_t index) { |
| if (!Initialize()) { |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| if (!SetupOwnerSession()) { |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| TPM_RC result = |
| trunks_utility_->DestroyNVSpace(index, trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error destroying nvram space:" << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| DeletePolicyRecord(index); |
| return NVRAM_RESULT_SUCCESS; |
| } |
| |
| NvramResult Tpm2NvramImpl::WriteSpace(uint32_t index, |
| const std::string& data, |
| const std::string& authorization_value) { |
| if (!Initialize()) { |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| trunks::TPMS_NV_PUBLIC nvram_public; |
| TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram space public area: " |
| << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| if (nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) { |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| trunks::AuthorizationDelegate* authorization = nullptr; |
| std::unique_ptr<trunks::PolicySession> policy_session = |
| trunks_factory_.GetPolicySession(); |
| bool using_owner_authorization = false; |
| bool extend = (nvram_public.attributes & trunks::TPMA_NV_EXTEND) != 0; |
| if (nvram_public.attributes & trunks::TPMA_NV_POLICYWRITE) { |
| NvramPolicyRecord policy_record; |
| if (!GetPolicyRecord(index, &policy_record)) { |
| LOG(ERROR) << "Policy record missing."; |
| return NVRAM_RESULT_INVALID_PARAMETER; |
| } |
| if (!SetupPolicySession( |
| policy_record, authorization_value, |
| extend ? trunks::TPM_CC_NV_Extend : trunks::TPM_CC_NV_Write, |
| policy_session.get())) { |
| // This will fail if policy is not met, e.g. a PCR value is not the |
| // required value. |
| return NVRAM_RESULT_ACCESS_DENIED; |
| } |
| authorization = policy_session->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHWRITE) { |
| trunks_session_->SetEntityAuthorizationValue(authorization_value); |
| authorization = trunks_session_->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERWRITE) { |
| if (!SetupOwnerSession()) { |
| // The owner password has been destroyed. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| using_owner_authorization = true; |
| authorization = trunks_session_->GetDelegate(); |
| } else { |
| // TPMA_NV_PPWRITE: Platform authorization is long gone. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| result = trunks_utility_->WriteNVSpace(index, 0 /* offset */, data, |
| using_owner_authorization, extend, |
| authorization); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error writing to nvram space: " << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| return NVRAM_RESULT_SUCCESS; |
| } |
| |
| NvramResult Tpm2NvramImpl::ReadSpace(uint32_t index, |
| std::string* data, |
| const std::string& authorization_value) { |
| if (!Initialize()) { |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| trunks::TPMS_NV_PUBLIC nvram_public; |
| TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram space public area: " |
| << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| if (nvram_public.attributes & trunks::TPMA_NV_READLOCKED) { |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| // Handle the case when the space has never been written to. |
| if ((nvram_public.attributes & trunks::TPMA_NV_WRITTEN) == 0) { |
| *data = std::string(nvram_public.data_size, 0); |
| return NVRAM_RESULT_SUCCESS; |
| } |
| trunks::AuthorizationDelegate* authorization = nullptr; |
| std::unique_ptr<trunks::PolicySession> policy_session = |
| trunks_factory_.GetPolicySession(); |
| bool using_owner_authorization = false; |
| if (nvram_public.attributes & trunks::TPMA_NV_POLICYREAD) { |
| NvramPolicyRecord policy_record; |
| if (!GetPolicyRecord(index, &policy_record)) { |
| LOG(ERROR) << "Policy record missing."; |
| return NVRAM_RESULT_INVALID_PARAMETER; |
| } |
| if (!SetupPolicySession(policy_record, authorization_value, |
| trunks::TPM_CC_NV_Read, policy_session.get())) { |
| // This will fail if policy is not met, e.g. a PCR value is not the |
| // required value. |
| return NVRAM_RESULT_ACCESS_DENIED; |
| } |
| authorization = policy_session->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHREAD) { |
| trunks_session_->SetEntityAuthorizationValue(authorization_value); |
| authorization = trunks_session_->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERREAD) { |
| if (!SetupOwnerSession()) { |
| // The owner password has been destroyed. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| using_owner_authorization = true; |
| authorization = trunks_session_->GetDelegate(); |
| } else { |
| // TPMA_NV_PPREAD: Platform authorization is long gone. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| result = trunks_utility_->ReadNVSpace( |
| index, 0 /* offset */, nvram_public.data_size, using_owner_authorization, |
| data, authorization); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram space: " << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| return NVRAM_RESULT_SUCCESS; |
| } |
| |
| NvramResult Tpm2NvramImpl::LockSpace(uint32_t index, |
| bool lock_read, |
| bool lock_write, |
| const std::string& authorization_value) { |
| if (!Initialize()) { |
| return NVRAM_RESULT_DEVICE_ERROR; |
| } |
| trunks::TPMS_NV_PUBLIC nvram_public; |
| TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram space public area: " |
| << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| bool is_read_locked = |
| ((nvram_public.attributes & trunks::TPMA_NV_READLOCKED) != 0); |
| bool is_write_locked = |
| ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0); |
| if ((!lock_read || is_read_locked) && (!lock_write || is_write_locked)) { |
| // Already locked. |
| return NVRAM_RESULT_SUCCESS; |
| } |
| // Handle locking read and write separately because the authorization might be |
| // different. |
| if (lock_read && !is_read_locked) { |
| trunks::AuthorizationDelegate* authorization = nullptr; |
| std::unique_ptr<trunks::PolicySession> policy_session = |
| trunks_factory_.GetPolicySession(); |
| bool using_owner_authorization = false; |
| if (nvram_public.attributes & trunks::TPMA_NV_POLICYREAD) { |
| NvramPolicyRecord policy_record; |
| if (!GetPolicyRecord(index, &policy_record)) { |
| LOG(ERROR) << "Policy record missing."; |
| return NVRAM_RESULT_INVALID_PARAMETER; |
| } |
| if (!SetupPolicySession(policy_record, authorization_value, |
| trunks::TPM_CC_NV_ReadLock, |
| policy_session.get())) { |
| // This will fail if policy is not met, e.g. a PCR value is not the |
| // required value. |
| return NVRAM_RESULT_ACCESS_DENIED; |
| } |
| authorization = policy_session->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHREAD) { |
| trunks_session_->SetEntityAuthorizationValue(authorization_value); |
| authorization = trunks_session_->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERREAD) { |
| if (!SetupOwnerSession()) { |
| // The owner password has been destroyed. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| using_owner_authorization = true; |
| authorization = trunks_session_->GetDelegate(); |
| } else { |
| // TPMA_NV_PPREAD: Platform authorization is long gone. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| result = trunks_utility_->LockNVSpace( |
| index, true /* lock_read */, false /* lock_write */, |
| using_owner_authorization, authorization); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| } |
| if (lock_write && !is_write_locked) { |
| trunks::AuthorizationDelegate* authorization = nullptr; |
| std::unique_ptr<trunks::PolicySession> policy_session = |
| trunks_factory_.GetPolicySession(); |
| bool using_owner_authorization = false; |
| if (nvram_public.attributes & trunks::TPMA_NV_POLICYWRITE) { |
| NvramPolicyRecord policy_record; |
| if (!GetPolicyRecord(index, &policy_record)) { |
| LOG(ERROR) << "Policy record missing."; |
| return NVRAM_RESULT_INVALID_PARAMETER; |
| } |
| if (!SetupPolicySession(policy_record, authorization_value, |
| trunks::TPM_CC_NV_WriteLock, |
| policy_session.get())) { |
| // This will fail if policy is not met, e.g. a PCR value is not the |
| // required value. |
| return NVRAM_RESULT_ACCESS_DENIED; |
| } |
| authorization = policy_session->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHWRITE) { |
| trunks_session_->SetEntityAuthorizationValue(authorization_value); |
| authorization = trunks_session_->GetDelegate(); |
| } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERWRITE) { |
| if (!SetupOwnerSession()) { |
| // The owner password has been destroyed. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| using_owner_authorization = true; |
| authorization = trunks_session_->GetDelegate(); |
| } else { |
| // TPMA_NV_PPWRITE: Platform authorization is long gone. |
| return NVRAM_RESULT_OPERATION_DISABLED; |
| } |
| result = trunks_utility_->LockNVSpace( |
| index, false /* lock_read */, true /* lock_write */, |
| using_owner_authorization, authorization); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| } |
| return NVRAM_RESULT_SUCCESS; |
| } |
| |
| NvramResult Tpm2NvramImpl::ListSpaces(std::vector<uint32_t>* index_list) { |
| return MapTpmError(trunks_utility_->ListNVSpaces(index_list)); |
| } |
| |
| NvramResult Tpm2NvramImpl::GetSpaceInfo( |
| uint32_t index, |
| size_t* size, |
| bool* is_read_locked, |
| bool* is_write_locked, |
| std::vector<NvramSpaceAttribute>* attributes, |
| NvramSpacePolicy* policy) { |
| trunks::TPMS_NV_PUBLIC nvram_public; |
| TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading NV space for index " << index |
| << " with error: " << GetErrorString(result); |
| return MapTpmError(result); |
| } |
| *size = nvram_public.data_size; |
| *is_read_locked = |
| ((nvram_public.attributes & trunks::TPMA_NV_READLOCKED) != 0); |
| *is_write_locked = |
| ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0); |
| MapAttributesFromTpm(nvram_public.attributes, attributes); |
| *policy = NVRAM_POLICY_NONE; |
| NvramPolicyRecord policy_record; |
| if (GetPolicyRecord(index, &policy_record)) { |
| *policy = policy_record.policy(); |
| if (!policy_record.world_read_allowed()) { |
| attributes->push_back(NVRAM_READ_AUTHORIZATION); |
| } |
| if (!policy_record.world_write_allowed()) { |
| attributes->push_back(NVRAM_WRITE_AUTHORIZATION); |
| } |
| } |
| return NVRAM_RESULT_SUCCESS; |
| } |
| |
| bool Tpm2NvramImpl::Initialize() { |
| if (initialized_) { |
| return true; |
| } |
| TPM_RC result = |
| trunks_session_->StartUnboundSession(true /* enable_encryption */); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting a default authorization session: " |
| << GetErrorString(result); |
| return false; |
| } |
| initialized_ = true; |
| return true; |
| } |
| |
| std::string Tpm2NvramImpl::GetOwnerPassword() { |
| LocalData local_data; |
| if (local_data_store_ && local_data_store_->Read(&local_data)) { |
| return local_data.owner_password(); |
| } |
| LOG(ERROR) << "TPM owner password requested but not available."; |
| return std::string(); |
| } |
| |
| bool Tpm2NvramImpl::SetupOwnerSession() { |
| std::string owner_password = GetOwnerPassword(); |
| if (owner_password.empty()) { |
| LOG(ERROR) << "Owner authorization required but not available."; |
| return false; |
| } |
| trunks_session_->SetEntityAuthorizationValue(owner_password); |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::SetupPolicySession( |
| const NvramPolicyRecord& policy_record, |
| const std::string& authorization_value, |
| trunks::TPM_CC command_code, |
| trunks::PolicySession* session) { |
| TPM_RC result = session->StartUnboundSession(true /* enable_encryption */); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting a policy authorization session: " |
| << GetErrorString(result); |
| return false; |
| } |
| session->SetEntityAuthorizationValue(authorization_value); |
| if (!AddPoliciesForCommand(policy_record, command_code, session)) { |
| return false; |
| } |
| if (!AddPolicyOR(policy_record, session)) { |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::AddPoliciesForCommand( |
| const NvramPolicyRecord& policy_record, |
| trunks::TPM_CC command_code, |
| trunks::PolicySession* session) { |
| TPM_RC result = session->PolicyCommandCode(command_code); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Failed to setup command code policy."; |
| return false; |
| } |
| bool is_write_command = (command_code == trunks::TPM_CC_NV_Write || |
| command_code == trunks::TPM_CC_NV_WriteLock || |
| command_code == trunks::TPM_CC_NV_Extend); |
| bool is_read_command = !is_write_command; |
| // Check if this operation requires an authorization value. |
| if ((is_read_command && !policy_record.world_read_allowed()) || |
| (is_write_command && !policy_record.world_write_allowed())) { |
| result = session->PolicyAuthValue(); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Failed to setup auth policy."; |
| return false; |
| } |
| } |
| if (policy_record.policy() == NVRAM_POLICY_PCR0) { |
| std::string current_pcr_value; |
| result = trunks_utility_->ReadPCR(0, ¤t_pcr_value); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Failed to read the current PCR value."; |
| return false; |
| } |
| result = session->PolicyPCR(0, current_pcr_value); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Failed to setup PCR policy."; |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::AddPolicyOR( |
| const NvramPolicyRecord& policy_record, |
| trunks::PolicySession* session) { |
| std::vector<std::string> digests; |
| for (int i = 0; i < policy_record.policy_digests_size(); ++i) { |
| digests.push_back(policy_record.policy_digests(i)); |
| } |
| TPM_RC result = session->PolicyOR(digests); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Failed to setup OR policy."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::ComputePolicyDigest(NvramPolicyRecord* policy_record, |
| std::string* digest) { |
| // Compute a policy digest for each command then OR them all together. This |
| // approach gives flexibility to have different requirements for read and |
| // write operations, and the ability to support authorization values combined |
| // with other policies. |
| std::unique_ptr<trunks::PolicySession> trial_session; |
| for (trunks::TPM_CC command_code : |
| {trunks::TPM_CC_NV_Extend, trunks::TPM_CC_NV_Write, |
| trunks::TPM_CC_NV_WriteLock, trunks::TPM_CC_NV_Read, |
| trunks::TPM_CC_NV_ReadLock, trunks::TPM_CC_NV_Certify}) { |
| trial_session = trunks_factory_.GetTrialSession(); |
| if (trial_session->StartUnboundSession(false /* enable_encryption */) != |
| TPM_RC_SUCCESS) { |
| return false; |
| } |
| if (!AddPoliciesForCommand(*policy_record, command_code, |
| trial_session.get())) { |
| return false; |
| } |
| if (trial_session->GetDigest(digest) != TPM_RC_SUCCESS) { |
| return false; |
| } |
| policy_record->add_policy_digests(*digest); |
| } |
| if (!AddPolicyOR(*policy_record, trial_session.get())) { |
| return false; |
| } |
| if (trial_session->GetDigest(digest) != TPM_RC_SUCCESS) { |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::GetPolicyRecord(uint32_t index, NvramPolicyRecord* record) { |
| LocalData local_data; |
| if (local_data_store_ && local_data_store_->Read(&local_data)) { |
| for (int i = 0; i < local_data.nvram_policy_size(); ++i) { |
| if (local_data.nvram_policy(i).index() == index) { |
| *record = local_data.nvram_policy(i); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| bool Tpm2NvramImpl::SavePolicyRecord(const NvramPolicyRecord& record) { |
| LocalData local_data; |
| if (!local_data_store_ || !local_data_store_->Read(&local_data)) { |
| LOG(ERROR) << "Failed to read local data."; |
| return false; |
| } |
| LocalData new_local_data = local_data; |
| new_local_data.clear_nvram_policy(); |
| for (int i = 0; i < local_data.nvram_policy_size(); ++i) { |
| // Keep only the ones that don't match |record|. |
| if (local_data.nvram_policy(i).index() != record.index()) { |
| *new_local_data.add_nvram_policy() = local_data.nvram_policy(i); |
| } |
| } |
| *new_local_data.add_nvram_policy() = record; |
| if (!local_data_store_->Write(new_local_data)) { |
| LOG(ERROR) << "Failed to write local data."; |
| return false; |
| } |
| return true; |
| } |
| |
| void Tpm2NvramImpl::DeletePolicyRecord(uint32_t index) { |
| LocalData local_data; |
| if (local_data_store_ && local_data_store_->Read(&local_data)) { |
| LocalData new_local_data = local_data; |
| new_local_data.clear_nvram_policy(); |
| for (int i = 0; i < local_data.nvram_policy_size(); ++i) { |
| // Keep only the ones that don't match |index|. |
| if (local_data.nvram_policy(i).index() != index) { |
| *new_local_data.add_nvram_policy() = local_data.nvram_policy(i); |
| } |
| } |
| local_data_store_->Write(new_local_data); |
| } |
| } |
| |
| } // namespace tpm_manager |