1// 2// Copyright (C) 2015 The Android Open Source Project 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17#include "tpm_manager/server/tpm2_nvram_impl.h" 18 19#include <memory> 20#include <string> 21 22#include <base/logging.h> 23#include <trunks/error_codes.h> 24#include <trunks/tpm_constants.h> 25#include <trunks/tpm_utility.h> 26#include <trunks/trunks_factory_impl.h> 27 28namespace tpm_manager { 29 30using trunks::GetErrorString; 31using trunks::TPM_RC; 32using trunks::TPM_RC_SUCCESS; 33 34Tpm2NvramImpl::Tpm2NvramImpl(LocalDataStore* local_data_store) 35 : trunks_factory_(new trunks::TrunksFactoryImpl()), 36 local_data_store_(local_data_store), 37 initialized_(false), 38 trunks_session_(trunks_factory_->GetHmacSession()), 39 trunks_utility_(trunks_factory_->GetTpmUtility()) {} 40 41Tpm2NvramImpl::Tpm2NvramImpl(std::unique_ptr<trunks::TrunksFactory> factory, 42 LocalDataStore* local_data_store) 43 : trunks_factory_(std::move(factory)), 44 local_data_store_(local_data_store), 45 initialized_(false), 46 trunks_session_(trunks_factory_->GetHmacSession()), 47 trunks_utility_(trunks_factory_->GetTpmUtility()) {} 48 49bool Tpm2NvramImpl::Initialize() { 50 if (initialized_) { 51 return true; 52 } 53 TPM_RC result = trunks_utility_->StartSession(trunks_session_.get()); 54 if (result != TPM_RC_SUCCESS) { 55 LOG(ERROR) << "Error starting an authorization session with trunks: " 56 << GetErrorString(result); 57 return false; 58 } 59 LocalData local_data; 60 if (!local_data_store_->Read(&local_data)) { 61 LOG(ERROR) << "Error reading local tpm data."; 62 return false; 63 } 64 if (!local_data.owner_password().empty()) { 65 owner_password_.assign(local_data.owner_password()); 66 initialized_ = true; 67 } 68 return true; 69} 70 71bool Tpm2NvramImpl::InitializeWithOwnerPassword() { 72 if (!Initialize()) { 73 return false; 74 } 75 if (owner_password_.empty()) { 76 LOG(ERROR) << "Error owner password not available."; 77 return false; 78 } 79 trunks_session_->SetEntityAuthorizationValue(owner_password_); 80 return true; 81} 82 83bool Tpm2NvramImpl::DefineNvram(uint32_t index, size_t length) { 84 if (!InitializeWithOwnerPassword()) { 85 return false; 86 } 87 TPM_RC result = trunks_utility_->DefineNVSpace( 88 index, length, trunks_session_->GetDelegate()); 89 if (result != TPM_RC_SUCCESS) { 90 LOG(ERROR) << "Error defining nvram space: " << GetErrorString(result); 91 return false; 92 } 93 return true; 94} 95 96bool Tpm2NvramImpl::DestroyNvram(uint32_t index) { 97 if (!InitializeWithOwnerPassword()) { 98 return false; 99 } 100 TPM_RC result = trunks_utility_->DestroyNVSpace( 101 index, trunks_session_->GetDelegate()); 102 if (result != TPM_RC_SUCCESS) { 103 LOG(ERROR) << "Error destroying nvram space:" << GetErrorString(result); 104 return false; 105 } 106 return true; 107} 108 109bool Tpm2NvramImpl::WriteNvram(uint32_t index, const std::string& data) { 110 if (!InitializeWithOwnerPassword()) { 111 return false; 112 } 113 TPM_RC result = trunks_utility_->WriteNVSpace(index, 114 0, // offset 115 data, 116 trunks_session_->GetDelegate()); 117 if (result != TPM_RC_SUCCESS) { 118 LOG(ERROR) << "Error writing to nvram space: " << GetErrorString(result); 119 return false; 120 } 121 result = trunks_utility_->LockNVSpace(index, trunks_session_->GetDelegate()); 122 if (result != TPM_RC_SUCCESS) { 123 LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result); 124 return false; 125 } 126 return true; 127} 128 129bool Tpm2NvramImpl::ReadNvram(uint32_t index, std::string* data) { 130 if (!Initialize()) { 131 return false; 132 } 133 size_t nvram_size; 134 if (!GetNvramSize(index, &nvram_size)) { 135 LOG(ERROR) << "Error getting size of nvram space."; 136 return false; 137 } 138 trunks_session_->SetEntityAuthorizationValue(""); 139 TPM_RC result = trunks_utility_->ReadNVSpace(index, 140 0, // offset 141 nvram_size, 142 data, 143 trunks_session_->GetDelegate()); 144 if (result != TPM_RC_SUCCESS) { 145 LOG(ERROR) << "Error reading nvram space: " << GetErrorString(result); 146 return false; 147 } 148 return true; 149} 150 151bool Tpm2NvramImpl::IsNvramDefined(uint32_t index, bool* defined) { 152 trunks::TPMS_NV_PUBLIC nvram_public; 153 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); 154 if (trunks::GetFormatOneError(result) == trunks::TPM_RC_HANDLE) { 155 *defined = false; 156 } else if (result == TPM_RC_SUCCESS) { 157 *defined = true; 158 } else { 159 LOG(ERROR) << "Error reading NV space for index " << index 160 << " with error: " << GetErrorString(result); 161 return false; 162 } 163 return true; 164} 165 166bool Tpm2NvramImpl::IsNvramLocked(uint32_t index, bool* locked) { 167 trunks::TPMS_NV_PUBLIC nvram_public; 168 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); 169 if (result != TPM_RC_SUCCESS) { 170 LOG(ERROR) << "Error reading NV space for index " << index 171 << " with error: " << GetErrorString(result); 172 return false; 173 } 174 *locked = ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0); 175 return true; 176} 177 178bool Tpm2NvramImpl::GetNvramSize(uint32_t index, size_t* size) { 179 trunks::TPMS_NV_PUBLIC nvram_public; 180 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public); 181 if (result != TPM_RC_SUCCESS) { 182 LOG(ERROR) << "Error reading NV space for index " << index 183 << " with error: " << GetErrorString(result); 184 return false; 185 } 186 *size = nvram_public.data_size; 187 return true; 188} 189 190} // namespace tpm_manager 191