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
28 namespace tpm_manager {
29
30 using trunks::GetErrorString;
31 using trunks::TPM_RC;
32 using trunks::TPM_RC_SUCCESS;
33
Tpm2NvramImpl(LocalDataStore * local_data_store)34 Tpm2NvramImpl::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
Tpm2NvramImpl(std::unique_ptr<trunks::TrunksFactory> factory,LocalDataStore * local_data_store)41 Tpm2NvramImpl::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
Initialize()49 bool 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
InitializeWithOwnerPassword()71 bool 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
DefineNvram(uint32_t index,size_t length)83 bool 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
DestroyNvram(uint32_t index)96 bool 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
WriteNvram(uint32_t index,const std::string & data)109 bool 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
ReadNvram(uint32_t index,std::string * data)129 bool 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
IsNvramDefined(uint32_t index,bool * defined)151 bool 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
IsNvramLocked(uint32_t index,bool * locked)166 bool 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
GetNvramSize(uint32_t index,size_t * size)178 bool 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