| // |
| // 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/tpm_constants.h> |
| #include <trunks/tpm_utility.h> |
| #include <trunks/trunks_factory_impl.h> |
| |
| namespace tpm_manager { |
| |
| using trunks::GetErrorString; |
| using trunks::TPM_RC; |
| using trunks::TPM_RC_SUCCESS; |
| |
| Tpm2NvramImpl::Tpm2NvramImpl(LocalDataStore* local_data_store) |
| : trunks_factory_(new trunks::TrunksFactoryImpl()), |
| local_data_store_(local_data_store), |
| initialized_(false), |
| trunks_session_(trunks_factory_->GetHmacSession()), |
| trunks_utility_(trunks_factory_->GetTpmUtility()) {} |
| |
| Tpm2NvramImpl::Tpm2NvramImpl(std::unique_ptr<trunks::TrunksFactory> factory, |
| LocalDataStore* local_data_store) |
| : trunks_factory_(std::move(factory)), |
| local_data_store_(local_data_store), |
| initialized_(false), |
| trunks_session_(trunks_factory_->GetHmacSession()), |
| trunks_utility_(trunks_factory_->GetTpmUtility()) {} |
| |
| bool Tpm2NvramImpl::Initialize() { |
| if (initialized_) { |
| return true; |
| } |
| TPM_RC result = trunks_utility_->StartSession(trunks_session_.get()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting an authorization session with trunks: " |
| << GetErrorString(result); |
| return false; |
| } |
| LocalData local_data; |
| if (!local_data_store_->Read(&local_data)) { |
| LOG(ERROR) << "Error reading local tpm data."; |
| return false; |
| } |
| if (!local_data.owner_password().empty()) { |
| owner_password_.assign(local_data.owner_password()); |
| initialized_ = true; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::InitializeWithOwnerPassword() { |
| if (!Initialize()) { |
| return false; |
| } |
| if (owner_password_.empty()) { |
| LOG(ERROR) << "Error owner password not available."; |
| return false; |
| } |
| trunks_session_->SetEntityAuthorizationValue(owner_password_); |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::DefineNvram(uint32_t index, size_t length) { |
| if (!InitializeWithOwnerPassword()) { |
| return false; |
| } |
| TPM_RC result = trunks_utility_->DefineNVSpace( |
| index, length, trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error defining nvram space: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::DestroyNvram(uint32_t index) { |
| if (!InitializeWithOwnerPassword()) { |
| return false; |
| } |
| TPM_RC result = |
| trunks_utility_->DestroyNVSpace(index, trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error destroying nvram space:" << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::WriteNvram(uint32_t index, const std::string& data) { |
| if (!InitializeWithOwnerPassword()) { |
| return false; |
| } |
| TPM_RC result = |
| trunks_utility_->WriteNVSpace(index, |
| 0, // offset |
| data, trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error writing to nvram space: " << GetErrorString(result); |
| return false; |
| } |
| result = trunks_utility_->LockNVSpace(index, trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::ReadNvram(uint32_t index, std::string* data) { |
| if (!Initialize()) { |
| return false; |
| } |
| size_t nvram_size; |
| if (!GetNvramSize(index, &nvram_size)) { |
| LOG(ERROR) << "Error getting size of nvram space."; |
| return false; |
| } |
| trunks_session_->SetEntityAuthorizationValue(""); |
| TPM_RC result = trunks_utility_->ReadNVSpace(index, |
| 0, // offset |
| nvram_size, data, |
| trunks_session_->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram space: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::IsNvramDefined(uint32_t index, bool* defined) { |
| trunks::TPMS_NV_PUBLIC nvram_public; |
| TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); |
| if (trunks::GetFormatOneError(result) == trunks::TPM_RC_HANDLE) { |
| *defined = false; |
| } else if (result == TPM_RC_SUCCESS) { |
| *defined = true; |
| } else { |
| LOG(ERROR) << "Error reading NV space for index " << index |
| << " with error: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::IsNvramLocked(uint32_t index, bool* locked) { |
| 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 false; |
| } |
| *locked = ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0); |
| return true; |
| } |
| |
| bool Tpm2NvramImpl::GetNvramSize(uint32_t index, size_t* size) { |
| 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 false; |
| } |
| *size = nvram_public.data_size; |
| return true; |
| } |
| |
| } // namespace tpm_manager |