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/tpm_nvram_impl.h"
18
19 #include <arpa/inet.h>
20
21 #include <string>
22
23 #include <base/logging.h>
24 #include <base/stl_util.h>
25 #include <trousers/scoped_tss_type.h>
26
27 #include "tpm_manager/common/local_data.pb.h"
28 #include "tpm_manager/server/local_data_store.h"
29 #include "tpm_manager/server/tpm_util.h"
30
31 namespace {
32
33 // PCR0 at locality 1 is used to differentiate between developed and normal
34 // mode. Restricting nvram to the PCR0 value in locality 1 prevents nvram from
35 // persisting across mode switch.
36 const unsigned int kTpmBootPCR = 0;
37 const unsigned int kTpmPCRLocality = 1;
38
39 } // namespace
40
41 namespace tpm_manager {
42
43 using trousers::ScopedTssMemory;
44 using trousers::ScopedTssNvStore;
45 using trousers::ScopedTssPcrs;
46
TpmNvramImpl(LocalDataStore * local_data_store)47 TpmNvramImpl::TpmNvramImpl(LocalDataStore* local_data_store)
48 : local_data_store_(local_data_store) {}
49
DefineNvram(uint32_t index,size_t length)50 bool TpmNvramImpl::DefineNvram(uint32_t index, size_t length) {
51 ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
52 if (!(InitializeNvramHandle(&nv_handle, index) &&
53 SetOwnerPolicy(&nv_handle))) {
54 return false;
55 }
56 TSS_RESULT result;
57 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_DATASIZE,
58 0, length);
59 if (TPM_ERROR(result)) {
60 TPM_LOG(ERROR, result) << "Could not set size on NVRAM object: " << length;
61 return false;
62 }
63 // Restrict to only one write.
64 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS,
65 0, TPM_NV_PER_WRITEDEFINE);
66 if (TPM_ERROR(result)) {
67 TPM_LOG(ERROR, result) << "Could not set PER_WRITEDEFINE on NVRAM object";
68 return false;
69 }
70 // Restrict to writing only with owner authorization.
71 result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS,
72 0, TPM_NV_PER_OWNERWRITE);
73 if (TPM_ERROR(result)) {
74 TPM_LOG(ERROR, result) << "Could not set PER_OWNERWRITE on NVRAM object";
75 return false;
76 }
77 ScopedTssPcrs pcr_handle(tpm_connection_.GetContext());
78 if (!SetCompositePcr0(&pcr_handle)) {
79 return false;
80 }
81 result = Tspi_NV_DefineSpace(nv_handle,
82 pcr_handle /* ReadPCRs restricted to PCR0 */,
83 pcr_handle /* WritePCRs restricted to PCR0 */);
84 if (TPM_ERROR(result)) {
85 TPM_LOG(ERROR, result) << "Could not define NVRAM space: " << index;
86 return false;
87 }
88 return true;
89 }
90
DestroyNvram(uint32_t index)91 bool TpmNvramImpl::DestroyNvram(uint32_t index) {
92 bool defined;
93 if (!IsNvramDefined(index, &defined)) {
94 return false;
95 }
96 if (!defined) {
97 // If the nvram space is not defined, we don't need to destroy it.
98 return true;
99 }
100 ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
101 if (!(InitializeNvramHandle(&nv_handle, index) &&
102 SetOwnerPolicy(&nv_handle))) {
103 return false;
104 }
105 TSS_RESULT result = Tspi_NV_ReleaseSpace(nv_handle);
106 if (TPM_ERROR(result)) {
107 TPM_LOG(ERROR, result) << "Could not release NVRAM space: " << index;
108 return false;
109 }
110 return true;
111 }
112
WriteNvram(uint32_t index,const std::string & data)113 bool TpmNvramImpl::WriteNvram(uint32_t index, const std::string& data) {
114 ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
115 if (!(InitializeNvramHandle(&nv_handle, index) &&
116 SetOwnerPolicy(&nv_handle))) {
117 return false;
118 }
119 TSS_RESULT result = Tspi_NV_WriteValue(
120 nv_handle, 0 /* offset */, data.size(),
121 reinterpret_cast<BYTE *>(const_cast<char*>(data.data())));
122 if (TPM_ERROR(result)) {
123 TPM_LOG(ERROR, result) << "Could not write to NVRAM space: " << index;
124 return false;
125 }
126 return true;
127 }
128
ReadNvram(uint32_t index,std::string * data)129 bool TpmNvramImpl::ReadNvram(uint32_t index, std::string* data) {
130 CHECK(data);
131 TSS_RESULT result;
132 ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
133 if (!InitializeNvramHandle(&nv_handle, index)) {
134 return false;
135 }
136 size_t nvram_size;
137 if (!GetNvramSize(index, &nvram_size)) {
138 return false;
139 }
140 data->resize(nvram_size);
141 // The Tpm1.2 Specification defines the maximum read size of 128 bytes.
142 // Therefore we have to loop through the data returned.
143 const size_t kMaxDataSize = 128;
144 uint32_t offset = 0;
145 while (offset < nvram_size) {
146 uint32_t chunk_size = std::max(nvram_size - offset, kMaxDataSize);
147 ScopedTssMemory space_data(tpm_connection_.GetContext());
148 if ((result = Tspi_NV_ReadValue(nv_handle, offset, &chunk_size,
149 space_data.ptr()))) {
150 TPM_LOG(ERROR, result) << "Could not read from NVRAM space: " << index;
151 return false;
152 }
153 if (!space_data.value()) {
154 LOG(ERROR) << "No data read from NVRAM space: " << index;
155 return false;
156 }
157 CHECK_LE((offset + chunk_size), data->size());
158 data->replace(offset,
159 chunk_size,
160 reinterpret_cast<char*>(space_data.value()),
161 chunk_size);
162 offset += chunk_size;
163 }
164 return true;
165 }
166
IsNvramDefined(uint32_t index,bool * defined)167 bool TpmNvramImpl::IsNvramDefined(uint32_t index, bool* defined) {
168 CHECK(defined);
169 uint32_t nv_list_data_length = 0;
170 ScopedTssMemory nv_list_data(tpm_connection_.GetContext());
171 TSS_RESULT result = Tspi_TPM_GetCapability(tpm_connection_.GetTpm(),
172 TSS_TPMCAP_NV_LIST,
173 0,
174 NULL,
175 &nv_list_data_length,
176 nv_list_data.ptr());
177 if (TPM_ERROR(result)) {
178 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
179 return false;
180 }
181 // Walk the list and check if the index exists.
182 uint32_t* nv_list = reinterpret_cast<uint32_t*>(nv_list_data.value());
183 uint32_t nv_list_length = nv_list_data_length / sizeof(uint32_t);
184 index = htonl(index); // TPM data is network byte order.
185 for (uint32_t i = 0; i < nv_list_length; ++i) {
186 if (index == nv_list[i]) {
187 *defined = true;
188 return true;
189 }
190 }
191 *defined = false;
192 return true;
193 }
194
IsNvramLocked(uint32_t index,bool * locked)195 bool TpmNvramImpl::IsNvramLocked(uint32_t index, bool* locked) {
196 CHECK(locked);
197 uint32_t nv_index_data_length = 0;
198 ScopedTssMemory nv_index_data(tpm_connection_.GetContext());
199 TSS_RESULT result = Tspi_TPM_GetCapability(tpm_connection_.GetTpm(),
200 TSS_TPMCAP_NV_INDEX,
201 sizeof(index),
202 reinterpret_cast<BYTE*>(&index),
203 &nv_index_data_length,
204 nv_index_data.ptr());
205 if (TPM_ERROR(result)) {
206 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
207 return false;
208 }
209 if (nv_index_data_length < (sizeof(uint32_t) + sizeof(TPM_BOOL))) {
210 return false;
211 }
212 // TPM_NV_DATA_PUBLIC->bWriteDefine is the second to last element in the
213 // struct.
214 uint32_t* nv_data_public = reinterpret_cast<uint32_t*>(
215 nv_index_data.value() + nv_index_data_length -
216 (sizeof(uint32_t) + sizeof(TPM_BOOL)));
217 *locked = (*nv_data_public != 0);
218 return true;
219 }
220
GetNvramSize(uint32_t index,size_t * size)221 bool TpmNvramImpl::GetNvramSize(uint32_t index, size_t* size) {
222 CHECK(size);
223 UINT32 nv_index_data_length = 0;
224 ScopedTssMemory nv_index_data(tpm_connection_.GetContext());
225 TSS_RESULT result = Tspi_TPM_GetCapability(tpm_connection_.GetTpm(),
226 TSS_TPMCAP_NV_INDEX,
227 sizeof(index),
228 reinterpret_cast<BYTE*>(&index),
229 &nv_index_data_length,
230 nv_index_data.ptr());
231 if (TPM_ERROR(result)) {
232 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
233 return false;
234 }
235 if (nv_index_data_length < sizeof(uint32_t)) {
236 return false;
237 }
238 // TPM_NV_DATA_PUBLIC->dataSize is the last element in the struct.
239 uint32_t* nv_data_public = reinterpret_cast<uint32_t*>(
240 nv_index_data.value() + nv_index_data_length -
241 sizeof(uint32_t));
242 *size = htonl(*nv_data_public);
243 return true;
244 }
245
InitializeNvramHandle(ScopedTssNvStore * nv_handle,uint32_t index)246 bool TpmNvramImpl::InitializeNvramHandle(ScopedTssNvStore* nv_handle,
247 uint32_t index) {
248
249 TSS_RESULT result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
250 TSS_OBJECT_TYPE_NV,
251 0,
252 nv_handle->ptr());
253 if (TPM_ERROR(result)) {
254 TPM_LOG(ERROR, result) << "Could not acquire an NVRAM object handle";
255 return false;
256 }
257 result = Tspi_SetAttribUint32(
258 nv_handle->value(), TSS_TSPATTRIB_NV_INDEX, 0, index);
259 if (TPM_ERROR(result)) {
260 TPM_LOG(ERROR, result) << "Could not set index on NVRAM object: " << index;
261 return false;
262 }
263 return true;
264 }
265
SetOwnerPolicy(ScopedTssNvStore * nv_handle)266 bool TpmNvramImpl::SetOwnerPolicy(ScopedTssNvStore* nv_handle) {
267 trousers::ScopedTssPolicy policy_handle(tpm_connection_.GetContext());
268 TSS_RESULT result;
269 result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
270 TSS_OBJECT_TYPE_POLICY,
271 TSS_POLICY_USAGE,
272 policy_handle.ptr());
273 if (TPM_ERROR(result)) {
274 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
275 return false;
276 }
277 std::string owner_password;
278 if (!GetOwnerPassword(&owner_password)) {
279 return false;
280 }
281 result = Tspi_Policy_SetSecret(
282 policy_handle,
283 TSS_SECRET_MODE_PLAIN,
284 owner_password.size(),
285 reinterpret_cast<BYTE *>(const_cast<char*>(owner_password.data())));
286 if (TPM_ERROR(result)) {
287 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
288 return false;
289 }
290 result = Tspi_Policy_AssignToObject(policy_handle.value(),
291 nv_handle->value());
292 if (TPM_ERROR(result)) {
293 TPM_LOG(ERROR, result) << "Could not set NVRAM object policy.";
294 return false;
295 }
296 return true;
297 }
298
SetCompositePcr0(ScopedTssPcrs * pcr_handle)299 bool TpmNvramImpl::SetCompositePcr0(ScopedTssPcrs* pcr_handle) {
300 TSS_RESULT result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
301 TSS_OBJECT_TYPE_PCRS,
302 TSS_PCRS_STRUCT_INFO_SHORT,
303 pcr_handle->ptr());
304 if (TPM_ERROR(result)) {
305 TPM_LOG(ERROR, result) << "Could not acquire PCR object handle";
306 return false;
307 }
308 uint32_t pcr_len;
309 std::string owner_password;
310 if (!GetOwnerPassword(&owner_password)) {
311 return false;
312 }
313 ScopedTssMemory pcr_value(tpm_connection_.GetContext());
314 result = Tspi_TPM_PcrRead(tpm_connection_.GetTpmWithAuth(owner_password),
315 kTpmBootPCR,
316 &pcr_len,
317 pcr_value.ptr());
318 if (TPM_ERROR(result)) {
319 TPM_LOG(ERROR, result) << "Could not read PCR0 value";
320 return false;
321 }
322 result = Tspi_PcrComposite_SetPcrValue(pcr_handle->value(),
323 kTpmBootPCR,
324 pcr_len,
325 pcr_value.value());
326 if (TPM_ERROR(result)) {
327 TPM_LOG(ERROR, result) << "Could not set value for PCR0 in PCR handle";
328 return false;
329 }
330 result = Tspi_PcrComposite_SetPcrLocality(pcr_handle->value(),
331 kTpmPCRLocality);
332 if (TPM_ERROR(result)) {
333 TPM_LOG(ERROR, result) << "Could not set locality for PCR0 in PCR handle";
334 return false;
335 }
336 return true;
337 }
338
GetOwnerPassword(std::string * owner_password)339 bool TpmNvramImpl::GetOwnerPassword(std::string* owner_password) {
340 LocalData local_data;
341 if (!local_data_store_->Read(&local_data)) {
342 LOG(ERROR) << "Error reading local data for owner password.";
343 return false;
344 }
345 if (local_data.owner_password().empty()) {
346 LOG(ERROR) << "No owner password present in tpm local_data.";
347 return false;
348 }
349 owner_password->assign(local_data.owner_password());
350 return true;
351 }
352
353 } // namespace tpm_manager
354