// // 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