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/policy_session.h>
25 #include <trunks/tpm_constants.h>
26 #include <trunks/tpm_utility.h>
27
28 namespace tpm_manager {
29
30 using trunks::GetErrorString;
31 using trunks::TPM_RC;
32 using trunks::TPM_RC_SUCCESS;
33
34 namespace {
35
MapAttributesFromTpm(trunks::TPMA_NV tpm_flags,std::vector<NvramSpaceAttribute> * attributes)36 void MapAttributesFromTpm(trunks::TPMA_NV tpm_flags,
37 std::vector<NvramSpaceAttribute>* attributes) {
38 if (tpm_flags & trunks::TPMA_NV_WRITEDEFINE)
39 attributes->push_back(NVRAM_PERSISTENT_WRITE_LOCK);
40 if (tpm_flags & trunks::TPMA_NV_WRITE_STCLEAR)
41 attributes->push_back(NVRAM_BOOT_WRITE_LOCK);
42 if (tpm_flags & trunks::TPMA_NV_READ_STCLEAR)
43 attributes->push_back(NVRAM_BOOT_READ_LOCK);
44 if (tpm_flags & (trunks::TPMA_NV_AUTHWRITE))
45 attributes->push_back(NVRAM_WRITE_AUTHORIZATION);
46 if (tpm_flags & (trunks::TPMA_NV_AUTHREAD))
47 attributes->push_back(NVRAM_READ_AUTHORIZATION);
48 if (tpm_flags & trunks::TPMA_NV_GLOBALLOCK)
49 attributes->push_back(NVRAM_GLOBAL_LOCK);
50 if (tpm_flags & trunks::TPMA_NV_PPWRITE)
51 attributes->push_back(NVRAM_PLATFORM_WRITE);
52 if (tpm_flags & trunks::TPMA_NV_OWNERWRITE)
53 attributes->push_back(NVRAM_OWNER_WRITE);
54 if (tpm_flags & trunks::TPMA_NV_OWNERREAD)
55 attributes->push_back(NVRAM_OWNER_READ);
56 if (tpm_flags & trunks::TPMA_NV_EXTEND)
57 attributes->push_back(NVRAM_WRITE_EXTEND);
58 }
59
MapAttributesToTpm(const std::vector<NvramSpaceAttribute> & attributes,trunks::TPMA_NV * tpm_flags,bool * world_read_allowed,bool * world_write_allowed)60 bool MapAttributesToTpm(
61 const std::vector<NvramSpaceAttribute>& attributes,
62 trunks::TPMA_NV* tpm_flags,
63 bool* world_read_allowed,
64 bool* world_write_allowed) {
65 // Always require policy, even if it's an empty policy.
66 *tpm_flags = trunks::TPMA_NV_POLICYWRITE | trunks::TPMA_NV_POLICYREAD;
67 *world_read_allowed = true;
68 *world_write_allowed = true;
69 for (auto attribute : attributes) {
70 switch (attribute) {
71 case NVRAM_PERSISTENT_WRITE_LOCK:
72 *tpm_flags |= trunks::TPMA_NV_WRITEDEFINE;
73 break;
74 case NVRAM_BOOT_WRITE_LOCK:
75 *tpm_flags |= trunks::TPMA_NV_WRITE_STCLEAR;
76 break;
77 case NVRAM_BOOT_READ_LOCK:
78 *tpm_flags |= trunks::TPMA_NV_READ_STCLEAR;
79 break;
80 case NVRAM_WRITE_AUTHORIZATION:
81 *world_write_allowed = false;
82 break;
83 case NVRAM_READ_AUTHORIZATION:
84 *world_read_allowed = false;
85 break;
86 case NVRAM_WRITE_EXTEND:
87 *tpm_flags |= trunks::TPMA_NV_EXTEND;
88 break;
89 case NVRAM_GLOBAL_LOCK:
90 case NVRAM_PLATFORM_WRITE:
91 case NVRAM_OWNER_WRITE:
92 case NVRAM_OWNER_READ:
93 return false;
94 default:
95 break;
96 }
97 }
98 return true;
99 }
100
MapTpmError(TPM_RC tpm_error)101 NvramResult MapTpmError(TPM_RC tpm_error) {
102 switch (trunks::GetFormatOneError(tpm_error)) {
103 case trunks::TPM_RC_SUCCESS:
104 return NVRAM_RESULT_SUCCESS;
105 case trunks::TPM_RC_NV_RANGE:
106 case trunks::TPM_RC_NV_SIZE:
107 case trunks::TPM_RC_ATTRIBUTES:
108 return NVRAM_RESULT_INVALID_PARAMETER;
109 case trunks::TPM_RC_NV_LOCKED:
110 case trunks::TPM_RC_NV_UNINITIALIZED:
111 return NVRAM_RESULT_OPERATION_DISABLED;
112 case trunks::TPM_RC_NV_AUTHORIZATION:
113 case trunks::TPM_RC_BAD_AUTH:
114 case trunks::TPM_RC_AUTH_FAIL:
115 case trunks::TPM_RC_POLICY_FAIL:
116 return NVRAM_RESULT_ACCESS_DENIED;
117 case trunks::TPM_RC_NV_SPACE:
118 return NVRAM_RESULT_INSUFFICIENT_SPACE;
119 case trunks::TPM_RC_NV_DEFINED:
120 return NVRAM_RESULT_SPACE_ALREADY_EXISTS;
121 case trunks::TPM_RC_HANDLE:
122 return NVRAM_RESULT_SPACE_DOES_NOT_EXIST;
123 }
124 return NVRAM_RESULT_DEVICE_ERROR;
125 }
126
127 } // namespace
128
Tpm2NvramImpl(const trunks::TrunksFactory & factory,LocalDataStore * local_data_store)129 Tpm2NvramImpl::Tpm2NvramImpl(const trunks::TrunksFactory& factory,
130 LocalDataStore* local_data_store)
131 : trunks_factory_(factory),
132 local_data_store_(local_data_store),
133 initialized_(false),
134 trunks_session_(trunks_factory_.GetHmacSession()),
135 trunks_utility_(trunks_factory_.GetTpmUtility()) {}
136
DefineSpace(uint32_t index,size_t size,const std::vector<NvramSpaceAttribute> & attributes,const std::string & authorization_value,NvramSpacePolicy policy)137 NvramResult Tpm2NvramImpl::DefineSpace(
138 uint32_t index,
139 size_t size,
140 const std::vector<NvramSpaceAttribute>& attributes,
141 const std::string& authorization_value,
142 NvramSpacePolicy policy) {
143 if (!Initialize()) {
144 return NVRAM_RESULT_DEVICE_ERROR;
145 }
146 if (!SetupOwnerSession()) {
147 return NVRAM_RESULT_OPERATION_DISABLED;
148 }
149 trunks::TPMA_NV attribute_flags = 0;
150 bool world_read_allowed = false;
151 bool world_write_allowed = false;
152 if (!MapAttributesToTpm(attributes, &attribute_flags, &world_read_allowed,
153 &world_write_allowed)) {
154 return NVRAM_RESULT_INVALID_PARAMETER;
155 }
156 NvramPolicyRecord policy_record;
157 policy_record.set_index(index);
158 policy_record.set_policy(policy);
159 policy_record.set_world_read_allowed(world_read_allowed);
160 policy_record.set_world_write_allowed(world_write_allowed);
161 std::string policy_digest;
162 if (!ComputePolicyDigest(&policy_record, &policy_digest)) {
163 LOG(ERROR) << "Failed to compute policy digest.";
164 return NVRAM_RESULT_DEVICE_ERROR;
165 }
166 TPM_RC result = trunks_utility_->DefineNVSpace(
167 index, size, attribute_flags, authorization_value, policy_digest,
168 trunks_session_->GetDelegate());
169 if (result != TPM_RC_SUCCESS) {
170 LOG(ERROR) << "Error defining nvram space: " << GetErrorString(result);
171 return MapTpmError(result);
172 }
173 if (!SavePolicyRecord(policy_record)) {
174 trunks_utility_->DestroyNVSpace(index, trunks_session_->GetDelegate());
175 return NVRAM_RESULT_DEVICE_ERROR;
176 }
177 return NVRAM_RESULT_SUCCESS;
178 }
179
DestroySpace(uint32_t index)180 NvramResult Tpm2NvramImpl::DestroySpace(uint32_t index) {
181 if (!Initialize()) {
182 return NVRAM_RESULT_DEVICE_ERROR;
183 }
184 if (!SetupOwnerSession()) {
185 return NVRAM_RESULT_OPERATION_DISABLED;
186 }
187 TPM_RC result =
188 trunks_utility_->DestroyNVSpace(index, trunks_session_->GetDelegate());
189 if (result != TPM_RC_SUCCESS) {
190 LOG(ERROR) << "Error destroying nvram space:" << GetErrorString(result);
191 return MapTpmError(result);
192 }
193 DeletePolicyRecord(index);
194 return NVRAM_RESULT_SUCCESS;
195 }
196
WriteSpace(uint32_t index,const std::string & data,const std::string & authorization_value)197 NvramResult Tpm2NvramImpl::WriteSpace(uint32_t index,
198 const std::string& data,
199 const std::string& authorization_value) {
200 if (!Initialize()) {
201 return NVRAM_RESULT_DEVICE_ERROR;
202 }
203 trunks::TPMS_NV_PUBLIC nvram_public;
204 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
205 if (result != TPM_RC_SUCCESS) {
206 LOG(ERROR) << "Error reading nvram space public area: "
207 << GetErrorString(result);
208 return MapTpmError(result);
209 }
210 if (nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) {
211 return NVRAM_RESULT_OPERATION_DISABLED;
212 }
213 trunks::AuthorizationDelegate* authorization = nullptr;
214 std::unique_ptr<trunks::PolicySession> policy_session =
215 trunks_factory_.GetPolicySession();
216 bool using_owner_authorization = false;
217 bool extend = (nvram_public.attributes & trunks::TPMA_NV_EXTEND) != 0;
218 if (nvram_public.attributes & trunks::TPMA_NV_POLICYWRITE) {
219 NvramPolicyRecord policy_record;
220 if (!GetPolicyRecord(index, &policy_record)) {
221 LOG(ERROR) << "Policy record missing.";
222 return NVRAM_RESULT_INVALID_PARAMETER;
223 }
224 if (!SetupPolicySession(
225 policy_record, authorization_value,
226 extend ? trunks::TPM_CC_NV_Extend : trunks::TPM_CC_NV_Write,
227 policy_session.get())) {
228 // This will fail if policy is not met, e.g. a PCR value is not the
229 // required value.
230 return NVRAM_RESULT_ACCESS_DENIED;
231 }
232 authorization = policy_session->GetDelegate();
233 } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHWRITE) {
234 trunks_session_->SetEntityAuthorizationValue(authorization_value);
235 authorization = trunks_session_->GetDelegate();
236 } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERWRITE) {
237 if (!SetupOwnerSession()) {
238 // The owner password has been destroyed.
239 return NVRAM_RESULT_OPERATION_DISABLED;
240 }
241 using_owner_authorization = true;
242 authorization = trunks_session_->GetDelegate();
243 } else {
244 // TPMA_NV_PPWRITE: Platform authorization is long gone.
245 return NVRAM_RESULT_OPERATION_DISABLED;
246 }
247 result = trunks_utility_->WriteNVSpace(index, 0 /* offset */, data,
248 using_owner_authorization, extend,
249 authorization);
250 if (result != TPM_RC_SUCCESS) {
251 LOG(ERROR) << "Error writing to nvram space: " << GetErrorString(result);
252 return MapTpmError(result);
253 }
254 return NVRAM_RESULT_SUCCESS;
255 }
256
ReadSpace(uint32_t index,std::string * data,const std::string & authorization_value)257 NvramResult Tpm2NvramImpl::ReadSpace(uint32_t index,
258 std::string* data,
259 const std::string& authorization_value) {
260 if (!Initialize()) {
261 return NVRAM_RESULT_DEVICE_ERROR;
262 }
263 trunks::TPMS_NV_PUBLIC nvram_public;
264 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
265 if (result != TPM_RC_SUCCESS) {
266 LOG(ERROR) << "Error reading nvram space public area: "
267 << GetErrorString(result);
268 return MapTpmError(result);
269 }
270 if (nvram_public.attributes & trunks::TPMA_NV_READLOCKED) {
271 return NVRAM_RESULT_OPERATION_DISABLED;
272 }
273 // Handle the case when the space has never been written to.
274 if ((nvram_public.attributes & trunks::TPMA_NV_WRITTEN) == 0) {
275 *data = std::string(nvram_public.data_size, 0);
276 return NVRAM_RESULT_SUCCESS;
277 }
278 trunks::AuthorizationDelegate* authorization = nullptr;
279 std::unique_ptr<trunks::PolicySession> policy_session =
280 trunks_factory_.GetPolicySession();
281 bool using_owner_authorization = false;
282 if (nvram_public.attributes & trunks::TPMA_NV_POLICYREAD) {
283 NvramPolicyRecord policy_record;
284 if (!GetPolicyRecord(index, &policy_record)) {
285 LOG(ERROR) << "Policy record missing.";
286 return NVRAM_RESULT_INVALID_PARAMETER;
287 }
288 if (!SetupPolicySession(policy_record, authorization_value,
289 trunks::TPM_CC_NV_Read, policy_session.get())) {
290 // This will fail if policy is not met, e.g. a PCR value is not the
291 // required value.
292 return NVRAM_RESULT_ACCESS_DENIED;
293 }
294 authorization = policy_session->GetDelegate();
295 } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHREAD) {
296 trunks_session_->SetEntityAuthorizationValue(authorization_value);
297 authorization = trunks_session_->GetDelegate();
298 } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERREAD) {
299 if (!SetupOwnerSession()) {
300 // The owner password has been destroyed.
301 return NVRAM_RESULT_OPERATION_DISABLED;
302 }
303 using_owner_authorization = true;
304 authorization = trunks_session_->GetDelegate();
305 } else {
306 // TPMA_NV_PPREAD: Platform authorization is long gone.
307 return NVRAM_RESULT_OPERATION_DISABLED;
308 }
309 result = trunks_utility_->ReadNVSpace(
310 index, 0 /* offset */, nvram_public.data_size, using_owner_authorization,
311 data, authorization);
312 if (result != TPM_RC_SUCCESS) {
313 LOG(ERROR) << "Error reading nvram space: " << GetErrorString(result);
314 return MapTpmError(result);
315 }
316 return NVRAM_RESULT_SUCCESS;
317 }
318
LockSpace(uint32_t index,bool lock_read,bool lock_write,const std::string & authorization_value)319 NvramResult Tpm2NvramImpl::LockSpace(uint32_t index,
320 bool lock_read,
321 bool lock_write,
322 const std::string& authorization_value) {
323 if (!Initialize()) {
324 return NVRAM_RESULT_DEVICE_ERROR;
325 }
326 trunks::TPMS_NV_PUBLIC nvram_public;
327 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
328 if (result != TPM_RC_SUCCESS) {
329 LOG(ERROR) << "Error reading nvram space public area: "
330 << GetErrorString(result);
331 return MapTpmError(result);
332 }
333 bool is_read_locked =
334 ((nvram_public.attributes & trunks::TPMA_NV_READLOCKED) != 0);
335 bool is_write_locked =
336 ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0);
337 if ((!lock_read || is_read_locked) && (!lock_write || is_write_locked)) {
338 // Already locked.
339 return NVRAM_RESULT_SUCCESS;
340 }
341 // Handle locking read and write separately because the authorization might be
342 // different.
343 if (lock_read && !is_read_locked) {
344 trunks::AuthorizationDelegate* authorization = nullptr;
345 std::unique_ptr<trunks::PolicySession> policy_session =
346 trunks_factory_.GetPolicySession();
347 bool using_owner_authorization = false;
348 if (nvram_public.attributes & trunks::TPMA_NV_POLICYREAD) {
349 NvramPolicyRecord policy_record;
350 if (!GetPolicyRecord(index, &policy_record)) {
351 LOG(ERROR) << "Policy record missing.";
352 return NVRAM_RESULT_INVALID_PARAMETER;
353 }
354 if (!SetupPolicySession(policy_record, authorization_value,
355 trunks::TPM_CC_NV_ReadLock,
356 policy_session.get())) {
357 // This will fail if policy is not met, e.g. a PCR value is not the
358 // required value.
359 return NVRAM_RESULT_ACCESS_DENIED;
360 }
361 authorization = policy_session->GetDelegate();
362 } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHREAD) {
363 trunks_session_->SetEntityAuthorizationValue(authorization_value);
364 authorization = trunks_session_->GetDelegate();
365 } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERREAD) {
366 if (!SetupOwnerSession()) {
367 // The owner password has been destroyed.
368 return NVRAM_RESULT_OPERATION_DISABLED;
369 }
370 using_owner_authorization = true;
371 authorization = trunks_session_->GetDelegate();
372 } else {
373 // TPMA_NV_PPREAD: Platform authorization is long gone.
374 return NVRAM_RESULT_OPERATION_DISABLED;
375 }
376 result = trunks_utility_->LockNVSpace(
377 index, true /* lock_read */, false /* lock_write */,
378 using_owner_authorization, authorization);
379 if (result != TPM_RC_SUCCESS) {
380 LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result);
381 return MapTpmError(result);
382 }
383 }
384 if (lock_write && !is_write_locked) {
385 trunks::AuthorizationDelegate* authorization = nullptr;
386 std::unique_ptr<trunks::PolicySession> policy_session =
387 trunks_factory_.GetPolicySession();
388 bool using_owner_authorization = false;
389 if (nvram_public.attributes & trunks::TPMA_NV_POLICYWRITE) {
390 NvramPolicyRecord policy_record;
391 if (!GetPolicyRecord(index, &policy_record)) {
392 LOG(ERROR) << "Policy record missing.";
393 return NVRAM_RESULT_INVALID_PARAMETER;
394 }
395 if (!SetupPolicySession(policy_record, authorization_value,
396 trunks::TPM_CC_NV_WriteLock,
397 policy_session.get())) {
398 // This will fail if policy is not met, e.g. a PCR value is not the
399 // required value.
400 return NVRAM_RESULT_ACCESS_DENIED;
401 }
402 authorization = policy_session->GetDelegate();
403 } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHWRITE) {
404 trunks_session_->SetEntityAuthorizationValue(authorization_value);
405 authorization = trunks_session_->GetDelegate();
406 } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERWRITE) {
407 if (!SetupOwnerSession()) {
408 // The owner password has been destroyed.
409 return NVRAM_RESULT_OPERATION_DISABLED;
410 }
411 using_owner_authorization = true;
412 authorization = trunks_session_->GetDelegate();
413 } else {
414 // TPMA_NV_PPWRITE: Platform authorization is long gone.
415 return NVRAM_RESULT_OPERATION_DISABLED;
416 }
417 result = trunks_utility_->LockNVSpace(
418 index, false /* lock_read */, true /* lock_write */,
419 using_owner_authorization, authorization);
420 if (result != TPM_RC_SUCCESS) {
421 LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result);
422 return MapTpmError(result);
423 }
424 }
425 return NVRAM_RESULT_SUCCESS;
426 }
427
ListSpaces(std::vector<uint32_t> * index_list)428 NvramResult Tpm2NvramImpl::ListSpaces(std::vector<uint32_t>* index_list) {
429 return MapTpmError(trunks_utility_->ListNVSpaces(index_list));
430 }
431
GetSpaceInfo(uint32_t index,size_t * size,bool * is_read_locked,bool * is_write_locked,std::vector<NvramSpaceAttribute> * attributes,NvramSpacePolicy * policy)432 NvramResult Tpm2NvramImpl::GetSpaceInfo(
433 uint32_t index,
434 size_t* size,
435 bool* is_read_locked,
436 bool* is_write_locked,
437 std::vector<NvramSpaceAttribute>* attributes,
438 NvramSpacePolicy* policy) {
439 trunks::TPMS_NV_PUBLIC nvram_public;
440 TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
441 if (result != TPM_RC_SUCCESS) {
442 LOG(ERROR) << "Error reading NV space for index " << index
443 << " with error: " << GetErrorString(result);
444 return MapTpmError(result);
445 }
446 *size = nvram_public.data_size;
447 *is_read_locked =
448 ((nvram_public.attributes & trunks::TPMA_NV_READLOCKED) != 0);
449 *is_write_locked =
450 ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0);
451 MapAttributesFromTpm(nvram_public.attributes, attributes);
452 *policy = NVRAM_POLICY_NONE;
453 NvramPolicyRecord policy_record;
454 if (GetPolicyRecord(index, &policy_record)) {
455 *policy = policy_record.policy();
456 if (!policy_record.world_read_allowed()) {
457 attributes->push_back(NVRAM_READ_AUTHORIZATION);
458 }
459 if (!policy_record.world_write_allowed()) {
460 attributes->push_back(NVRAM_WRITE_AUTHORIZATION);
461 }
462 }
463 return NVRAM_RESULT_SUCCESS;
464 }
465
Initialize()466 bool Tpm2NvramImpl::Initialize() {
467 if (initialized_) {
468 return true;
469 }
470 TPM_RC result =
471 trunks_session_->StartUnboundSession(true /* enable_encryption */);
472 if (result != TPM_RC_SUCCESS) {
473 LOG(ERROR) << "Error starting a default authorization session: "
474 << GetErrorString(result);
475 return false;
476 }
477 initialized_ = true;
478 return true;
479 }
480
GetOwnerPassword()481 std::string Tpm2NvramImpl::GetOwnerPassword() {
482 LocalData local_data;
483 if (local_data_store_ && local_data_store_->Read(&local_data)) {
484 return local_data.owner_password();
485 }
486 LOG(ERROR) << "TPM owner password requested but not available.";
487 return std::string();
488 }
489
SetupOwnerSession()490 bool Tpm2NvramImpl::SetupOwnerSession() {
491 std::string owner_password = GetOwnerPassword();
492 if (owner_password.empty()) {
493 LOG(ERROR) << "Owner authorization required but not available.";
494 return false;
495 }
496 trunks_session_->SetEntityAuthorizationValue(owner_password);
497 return true;
498 }
499
SetupPolicySession(const NvramPolicyRecord & policy_record,const std::string & authorization_value,trunks::TPM_CC command_code,trunks::PolicySession * session)500 bool Tpm2NvramImpl::SetupPolicySession(
501 const NvramPolicyRecord& policy_record,
502 const std::string& authorization_value,
503 trunks::TPM_CC command_code,
504 trunks::PolicySession* session) {
505 TPM_RC result = session->StartUnboundSession(true /* enable_encryption */);
506 if (result != TPM_RC_SUCCESS) {
507 LOG(ERROR) << "Error starting a policy authorization session: "
508 << GetErrorString(result);
509 return false;
510 }
511 session->SetEntityAuthorizationValue(authorization_value);
512 if (!AddPoliciesForCommand(policy_record, command_code, session)) {
513 return false;
514 }
515 if (!AddPolicyOR(policy_record, session)) {
516 return false;
517 }
518 return true;
519 }
520
AddPoliciesForCommand(const NvramPolicyRecord & policy_record,trunks::TPM_CC command_code,trunks::PolicySession * session)521 bool Tpm2NvramImpl::AddPoliciesForCommand(
522 const NvramPolicyRecord& policy_record,
523 trunks::TPM_CC command_code,
524 trunks::PolicySession* session) {
525 TPM_RC result = session->PolicyCommandCode(command_code);
526 if (result != TPM_RC_SUCCESS) {
527 LOG(ERROR) << "Failed to setup command code policy.";
528 return false;
529 }
530 bool is_write_command = (command_code == trunks::TPM_CC_NV_Write ||
531 command_code == trunks::TPM_CC_NV_WriteLock ||
532 command_code == trunks::TPM_CC_NV_Extend);
533 bool is_read_command = !is_write_command;
534 // Check if this operation requires an authorization value.
535 if ((is_read_command && !policy_record.world_read_allowed()) ||
536 (is_write_command && !policy_record.world_write_allowed())) {
537 result = session->PolicyAuthValue();
538 if (result != TPM_RC_SUCCESS) {
539 LOG(ERROR) << "Failed to setup auth policy.";
540 return false;
541 }
542 }
543 if (policy_record.policy() == NVRAM_POLICY_PCR0) {
544 std::string current_pcr_value;
545 result = trunks_utility_->ReadPCR(0, ¤t_pcr_value);
546 if (result != TPM_RC_SUCCESS) {
547 LOG(ERROR) << "Failed to read the current PCR value.";
548 return false;
549 }
550 result = session->PolicyPCR(0, current_pcr_value);
551 if (result != TPM_RC_SUCCESS) {
552 LOG(ERROR) << "Failed to setup PCR policy.";
553 return false;
554 }
555 }
556 return true;
557 }
558
AddPolicyOR(const NvramPolicyRecord & policy_record,trunks::PolicySession * session)559 bool Tpm2NvramImpl::AddPolicyOR(
560 const NvramPolicyRecord& policy_record,
561 trunks::PolicySession* session) {
562 std::vector<std::string> digests;
563 for (int i = 0; i < policy_record.policy_digests_size(); ++i) {
564 digests.push_back(policy_record.policy_digests(i));
565 }
566 TPM_RC result = session->PolicyOR(digests);
567 if (result != TPM_RC_SUCCESS) {
568 LOG(ERROR) << "Failed to setup OR policy.";
569 return false;
570 }
571 return true;
572 }
573
ComputePolicyDigest(NvramPolicyRecord * policy_record,std::string * digest)574 bool Tpm2NvramImpl::ComputePolicyDigest(NvramPolicyRecord* policy_record,
575 std::string* digest) {
576 // Compute a policy digest for each command then OR them all together. This
577 // approach gives flexibility to have different requirements for read and
578 // write operations, and the ability to support authorization values combined
579 // with other policies.
580 std::unique_ptr<trunks::PolicySession> trial_session;
581 for (trunks::TPM_CC command_code :
582 {trunks::TPM_CC_NV_Extend, trunks::TPM_CC_NV_Write,
583 trunks::TPM_CC_NV_WriteLock, trunks::TPM_CC_NV_Read,
584 trunks::TPM_CC_NV_ReadLock, trunks::TPM_CC_NV_Certify}) {
585 trial_session = trunks_factory_.GetTrialSession();
586 if (trial_session->StartUnboundSession(false /* enable_encryption */) !=
587 TPM_RC_SUCCESS) {
588 return false;
589 }
590 if (!AddPoliciesForCommand(*policy_record, command_code,
591 trial_session.get())) {
592 return false;
593 }
594 if (trial_session->GetDigest(digest) != TPM_RC_SUCCESS) {
595 return false;
596 }
597 policy_record->add_policy_digests(*digest);
598 }
599 if (!AddPolicyOR(*policy_record, trial_session.get())) {
600 return false;
601 }
602 if (trial_session->GetDigest(digest) != TPM_RC_SUCCESS) {
603 return false;
604 }
605 return true;
606 }
607
GetPolicyRecord(uint32_t index,NvramPolicyRecord * record)608 bool Tpm2NvramImpl::GetPolicyRecord(uint32_t index, NvramPolicyRecord* record) {
609 LocalData local_data;
610 if (local_data_store_ && local_data_store_->Read(&local_data)) {
611 for (int i = 0; i < local_data.nvram_policy_size(); ++i) {
612 if (local_data.nvram_policy(i).index() == index) {
613 *record = local_data.nvram_policy(i);
614 return true;
615 }
616 }
617 }
618 return false;
619 }
620
SavePolicyRecord(const NvramPolicyRecord & record)621 bool Tpm2NvramImpl::SavePolicyRecord(const NvramPolicyRecord& record) {
622 LocalData local_data;
623 if (!local_data_store_ || !local_data_store_->Read(&local_data)) {
624 LOG(ERROR) << "Failed to read local data.";
625 return false;
626 }
627 LocalData new_local_data = local_data;
628 new_local_data.clear_nvram_policy();
629 for (int i = 0; i < local_data.nvram_policy_size(); ++i) {
630 // Keep only the ones that don't match |record|.
631 if (local_data.nvram_policy(i).index() != record.index()) {
632 *new_local_data.add_nvram_policy() = local_data.nvram_policy(i);
633 }
634 }
635 *new_local_data.add_nvram_policy() = record;
636 if (!local_data_store_->Write(new_local_data)) {
637 LOG(ERROR) << "Failed to write local data.";
638 return false;
639 }
640 return true;
641 }
642
DeletePolicyRecord(uint32_t index)643 void Tpm2NvramImpl::DeletePolicyRecord(uint32_t index) {
644 LocalData local_data;
645 if (local_data_store_ && local_data_store_->Read(&local_data)) {
646 LocalData new_local_data = local_data;
647 new_local_data.clear_nvram_policy();
648 for (int i = 0; i < local_data.nvram_policy_size(); ++i) {
649 // Keep only the ones that don't match |index|.
650 if (local_data.nvram_policy(i).index() != index) {
651 *new_local_data.add_nvram_policy() = local_data.nvram_policy(i);
652 }
653 }
654 local_data_store_->Write(new_local_data);
655 }
656 }
657
658 } // namespace tpm_manager
659