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 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 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 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 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 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 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 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 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 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 428 NvramResult Tpm2NvramImpl::ListSpaces(std::vector<uint32_t>* index_list) { 429 return MapTpmError(trunks_utility_->ListNVSpaces(index_list)); 430 } 431 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 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 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 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 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 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 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 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 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 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 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