//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "tpm_manager/server/tpm2_nvram_impl.h"

#include <map>
#include <memory>
#include <string>
#include <vector>

#include <base/logging.h>
#include <trunks/authorization_delegate.h>
#include <trunks/error_codes.h>
#include <trunks/policy_session.h>
#include <trunks/scoped_global_session.h>
#include <trunks/tpm_constants.h>
#include <trunks/tpm_utility.h>
#include <trunks/tpm_utility_impl.h>

namespace tpm_manager {

using trunks::GetErrorString;
using trunks::TPM_RC;
using trunks::TPM_RC_SUCCESS;

namespace {

void MapAttributesFromTpm(trunks::TPMA_NV tpm_flags,
                          std::vector<NvramSpaceAttribute>* attributes) {
  if (tpm_flags & trunks::TPMA_NV_WRITEDEFINE)
    attributes->push_back(NVRAM_PERSISTENT_WRITE_LOCK);
  if (tpm_flags & trunks::TPMA_NV_WRITE_STCLEAR)
    attributes->push_back(NVRAM_BOOT_WRITE_LOCK);
  if (tpm_flags & trunks::TPMA_NV_READ_STCLEAR)
    attributes->push_back(NVRAM_BOOT_READ_LOCK);
  if (tpm_flags & (trunks::TPMA_NV_AUTHWRITE))
    attributes->push_back(NVRAM_WRITE_AUTHORIZATION);
  if (tpm_flags & (trunks::TPMA_NV_AUTHREAD))
    attributes->push_back(NVRAM_READ_AUTHORIZATION);
  if (tpm_flags & trunks::TPMA_NV_GLOBALLOCK)
    attributes->push_back(NVRAM_GLOBAL_LOCK);
  if (tpm_flags & trunks::TPMA_NV_PPWRITE)
    attributes->push_back(NVRAM_PLATFORM_WRITE);
  if (tpm_flags & trunks::TPMA_NV_OWNERWRITE)
    attributes->push_back(NVRAM_OWNER_WRITE);
  if (tpm_flags & trunks::TPMA_NV_OWNERREAD)
    attributes->push_back(NVRAM_OWNER_READ);
  if (tpm_flags & trunks::TPMA_NV_EXTEND)
    attributes->push_back(NVRAM_WRITE_EXTEND);
  if (tpm_flags & (trunks::TPMA_NV_PPREAD))
    attributes->push_back(NVRAM_PLATFORM_READ);
}

bool MapAttributesToTpm(
    const std::vector<NvramSpaceAttribute>& attributes,
    NvramSpacePolicy policy,
    trunks::TPMA_NV* tpm_flags,
    bool* world_read_allowed,
    bool* world_write_allowed) {
  if (policy == NVRAM_POLICY_NONE) {
    *tpm_flags = trunks::TPMA_NV_AUTHWRITE | trunks::TPMA_NV_AUTHREAD;
  } else {
    *tpm_flags = trunks::TPMA_NV_POLICYWRITE | trunks::TPMA_NV_POLICYREAD;
  }
  *world_read_allowed = true;
  *world_write_allowed = true;
  for (auto attribute : attributes) {
    switch (attribute) {
      case NVRAM_PERSISTENT_WRITE_LOCK:
        *tpm_flags |= trunks::TPMA_NV_WRITEDEFINE;
        break;
      case NVRAM_BOOT_WRITE_LOCK:
        *tpm_flags |= trunks::TPMA_NV_WRITE_STCLEAR;
        break;
      case NVRAM_BOOT_READ_LOCK:
        *tpm_flags |= trunks::TPMA_NV_READ_STCLEAR;
        break;
      case NVRAM_WRITE_AUTHORIZATION:
        *world_write_allowed = false;
        break;
      case NVRAM_READ_AUTHORIZATION:
        *world_read_allowed = false;
        break;
      case NVRAM_WRITE_EXTEND:
        *tpm_flags |= trunks::TPMA_NV_EXTEND;
        break;
      case NVRAM_PLATFORM_READ:
        *tpm_flags |= trunks::TPMA_NV_PPREAD;
        break;
      case NVRAM_GLOBAL_LOCK:
      case NVRAM_PLATFORM_WRITE:
      case NVRAM_OWNER_WRITE:
      case NVRAM_OWNER_READ:
        return false;
      default:
        break;
    }
  }
  return true;
}

NvramResult MapTpmError(TPM_RC tpm_error) {
  switch (trunks::GetFormatOneError(tpm_error)) {
    case trunks::TPM_RC_SUCCESS:
      return NVRAM_RESULT_SUCCESS;
    case trunks::TPM_RC_NV_RANGE:
    case trunks::TPM_RC_NV_SIZE:
    case trunks::TPM_RC_ATTRIBUTES:
      return NVRAM_RESULT_INVALID_PARAMETER;
    case trunks::TPM_RC_NV_LOCKED:
    case trunks::TPM_RC_NV_UNINITIALIZED:
      return NVRAM_RESULT_OPERATION_DISABLED;
    case trunks::TPM_RC_NV_AUTHORIZATION:
    case trunks::TPM_RC_BAD_AUTH:
    case trunks::TPM_RC_AUTH_FAIL:
    case trunks::TPM_RC_POLICY_FAIL:
      return NVRAM_RESULT_ACCESS_DENIED;
    case trunks::TPM_RC_NV_SPACE:
      return NVRAM_RESULT_INSUFFICIENT_SPACE;
    case trunks::TPM_RC_NV_DEFINED:
      return NVRAM_RESULT_SPACE_ALREADY_EXISTS;
    case trunks::TPM_RC_HANDLE:
      return NVRAM_RESULT_SPACE_DOES_NOT_EXIST;
  }
  return NVRAM_RESULT_DEVICE_ERROR;
}

}  // namespace

Tpm2NvramImpl::Tpm2NvramImpl(const trunks::TrunksFactory& factory,
                             LocalDataStore* local_data_store,
                             TpmStatus* tpm_status)
    : trunks_factory_(factory),
      local_data_store_(local_data_store),
      tpm_status_(tpm_status),
      initialized_(false),
#ifndef TRUNKS_USE_PER_OP_SESSIONS
      trunks_session_(trunks_factory_.GetHmacSession()),
#endif
      trunks_utility_(trunks_factory_.GetTpmUtility()) {}

NvramResult Tpm2NvramImpl::DefineSpace(
    uint32_t index,
    size_t size,
    const std::vector<NvramSpaceAttribute>& attributes,
    const std::string& authorization_value,
    NvramSpacePolicy policy) {
  if (!Initialize()) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }

  trunks::TPMA_NV attribute_flags = 0;
  bool world_read_allowed = false;
  bool world_write_allowed = false;
  if (!MapAttributesToTpm(attributes, policy,
                          &attribute_flags, &world_read_allowed,
                          &world_write_allowed)) {
    return NVRAM_RESULT_INVALID_PARAMETER;
  }
  NvramPolicyRecord policy_record;
  policy_record.set_index(index);
  policy_record.set_policy(policy);
  policy_record.set_world_read_allowed(world_read_allowed);
  policy_record.set_world_write_allowed(world_write_allowed);
  std::string policy_digest;
  if (!ComputePolicyDigest(&policy_record, &policy_digest)) {
    LOG(ERROR) << "Failed to compute policy digest.";
    return NVRAM_RESULT_DEVICE_ERROR;
  }

  NvIndexAuthenticator nvindex_auth(tpm_status_, &trunks_session_,
      trunks_factory_);
  trunks::AuthorizationDelegate* delegate =
      nvindex_auth.GetOwnerAuthDelegate(GetOwnerPassword());
  if (!delegate) {
    return NVRAM_RESULT_OPERATION_DISABLED;
  }

  TPM_RC result = trunks_utility_->DefineNVSpace(
      index, size, attribute_flags, authorization_value, policy_digest,
      delegate);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error defining nvram space: " << GetErrorString(result);
    return MapTpmError(result);
  }
  if (!SavePolicyRecord(policy_record)) {
    trunks_utility_->DestroyNVSpace(index, delegate);
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  return NVRAM_RESULT_SUCCESS;
}

NvramResult Tpm2NvramImpl::DestroySpace(uint32_t index) {
  if (!Initialize()) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  trunks::ScopedGlobalHmacSession session_scope(&trunks_factory_,
                                                kGlobalSessionSalted,
                                                kGlobalSessionEncryption,
                                                &trunks_session_);
  if (!trunks_session_) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  if (!SetupOwnerSession()) {
    return NVRAM_RESULT_OPERATION_DISABLED;
  }
  TPM_RC result =
      trunks_utility_->DestroyNVSpace(index, trunks_session_->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error destroying nvram space:" << GetErrorString(result);
    return MapTpmError(result);
  }
  DeletePolicyRecord(index);
  return NVRAM_RESULT_SUCCESS;
}

NvramResult Tpm2NvramImpl::WriteSpace(uint32_t index,
                                      const std::string& data,
                                      const std::string& authorization_value) {
  if (!Initialize()) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  trunks::TPMS_NV_PUBLIC nvram_public;
  TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading nvram space public area: "
               << GetErrorString(result);
    return MapTpmError(result);
  }
  if (nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) {
    return NVRAM_RESULT_OPERATION_DISABLED;
  }
  NvIndexAuthenticator nvindex_auth(tpm_status_, &trunks_session_,
      trunks_factory_);
  trunks::AuthorizationDelegate* authorization = nullptr;
  std::unique_ptr<trunks::PolicySession> policy_session =
      trunks_factory_.GetPolicySession();
  bool using_owner_authorization = false;
  bool extend = (nvram_public.attributes & trunks::TPMA_NV_EXTEND) != 0;
  if (nvram_public.attributes & trunks::TPMA_NV_POLICYWRITE) {
    NvramPolicyRecord policy_record;
    if (!GetPolicyRecord(index, &policy_record)) {
      LOG(ERROR) << "Policy record missing.";
      return NVRAM_RESULT_INVALID_PARAMETER;
    }
    if (!SetupPolicySession(
            policy_record, authorization_value,
            extend ? trunks::TPM_CC_NV_Extend : trunks::TPM_CC_NV_Write,
            policy_session.get())) {
      // This will fail if policy is not met, e.g. a PCR value is not the
      // required value.
      return NVRAM_RESULT_ACCESS_DENIED;
    }
    authorization = policy_session->GetDelegate();
  } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHWRITE) {
    authorization = nvindex_auth.GetDirectAuthDelegate(authorization_value);
  } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERWRITE) {
    using_owner_authorization = true;
    authorization = nvindex_auth.GetOwnerAuthDelegate(GetOwnerPassword());
  } else {
    // TPMA_NV_PPWRITE: Platform authorization is long gone.
    return NVRAM_RESULT_OPERATION_DISABLED;
  }
  if (!authorization) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  result = trunks_utility_->WriteNVSpace(index, 0 /* offset */, data,
                                         using_owner_authorization, extend,
                                         authorization);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error writing to nvram space: " << GetErrorString(result);
    return MapTpmError(result);
  }
  return NVRAM_RESULT_SUCCESS;
}

NvramResult Tpm2NvramImpl::ReadSpace(uint32_t index,
                                     std::string* data,
                                     const std::string& authorization_value) {
  CHECK(data);
  if (!Initialize()) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  trunks::TPMS_NV_PUBLIC nvram_public;
  TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading nvram space public area: "
               << GetErrorString(result);
    return MapTpmError(result);
  }
  if (nvram_public.attributes & trunks::TPMA_NV_READLOCKED) {
    return NVRAM_RESULT_OPERATION_DISABLED;
  }
  // Handle the case when the space has never been written to.
  if ((nvram_public.attributes & trunks::TPMA_NV_WRITTEN) == 0) {
    *data = std::string(nvram_public.data_size, 0);
    return NVRAM_RESULT_SUCCESS;
  }
  NvIndexAuthenticator nvindex_auth(tpm_status_, &trunks_session_,
      trunks_factory_);
  trunks::AuthorizationDelegate* authorization = nullptr;
  std::unique_ptr<trunks::PolicySession> policy_session =
      trunks_factory_.GetPolicySession();
  bool using_owner_authorization = false;
  if (nvram_public.attributes & trunks::TPMA_NV_POLICYREAD) {
    NvramPolicyRecord policy_record;
    if (!GetPolicyRecord(index, &policy_record)) {
      LOG(ERROR) << "Policy record missing.";
      return NVRAM_RESULT_INVALID_PARAMETER;
    }
    if (!SetupPolicySession(policy_record, authorization_value,
                            trunks::TPM_CC_NV_Read, policy_session.get())) {
      // This will fail if policy is not met, e.g. a PCR value is not the
      // required value.
      return NVRAM_RESULT_ACCESS_DENIED;
    }
    authorization = policy_session->GetDelegate();
  } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHREAD) {
    authorization = nvindex_auth.GetDirectAuthDelegate(authorization_value);
  } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERREAD) {
    using_owner_authorization = true;
    authorization = nvindex_auth.GetOwnerAuthDelegate(GetOwnerPassword());
  } else {
    // TPMA_NV_PPREAD: Platform authorization is long gone.
    return NVRAM_RESULT_OPERATION_DISABLED;
  }
  if (!authorization) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  result = trunks_utility_->ReadNVSpace(
      index, 0 /* offset */, nvram_public.data_size, using_owner_authorization,
      data, authorization);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading nvram space: " << GetErrorString(result);
    return MapTpmError(result);
  }
  return NVRAM_RESULT_SUCCESS;
}

NvramResult Tpm2NvramImpl::LockSpace(uint32_t index,
                                     bool lock_read,
                                     bool lock_write,
                                     const std::string& authorization_value) {
  if (!Initialize()) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  trunks::ScopedGlobalHmacSession session_scope(&trunks_factory_,
                                                kGlobalSessionSalted,
                                                kGlobalSessionEncryption,
                                                &trunks_session_);
  if (!trunks_session_) {
    return NVRAM_RESULT_DEVICE_ERROR;
  }
  trunks::TPMS_NV_PUBLIC nvram_public;
  TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading nvram space public area: "
               << GetErrorString(result);
    return MapTpmError(result);
  }
  bool is_read_locked =
      ((nvram_public.attributes & trunks::TPMA_NV_READLOCKED) != 0);
  bool is_write_locked =
      ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0);
  if ((!lock_read || is_read_locked) && (!lock_write || is_write_locked)) {
    // Already locked.
    return NVRAM_RESULT_SUCCESS;
  }
  // Handle locking read and write separately because the authorization might be
  // different.
  if (lock_read && !is_read_locked) {
    trunks::AuthorizationDelegate* authorization = nullptr;
    std::unique_ptr<trunks::PolicySession> policy_session =
        trunks_factory_.GetPolicySession();
    bool using_owner_authorization = false;
    if (nvram_public.attributes & trunks::TPMA_NV_POLICYREAD) {
      NvramPolicyRecord policy_record;
      if (!GetPolicyRecord(index, &policy_record)) {
        LOG(ERROR) << "Policy record missing.";
        return NVRAM_RESULT_INVALID_PARAMETER;
      }
      if (!SetupPolicySession(policy_record, authorization_value,
                              trunks::TPM_CC_NV_ReadLock,
                              policy_session.get())) {
        // This will fail if policy is not met, e.g. a PCR value is not the
        // required value.
        return NVRAM_RESULT_ACCESS_DENIED;
      }
      authorization = policy_session->GetDelegate();
    } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHREAD) {
      trunks_session_->SetEntityAuthorizationValue(authorization_value);
      authorization = trunks_session_->GetDelegate();
    } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERREAD) {
      if (!SetupOwnerSession()) {
        // The owner password has been destroyed.
        return NVRAM_RESULT_OPERATION_DISABLED;
      }
      using_owner_authorization = true;
      authorization = trunks_session_->GetDelegate();
    } else {
      // TPMA_NV_PPREAD: Platform authorization is long gone.
      return NVRAM_RESULT_OPERATION_DISABLED;
    }
    result = trunks_utility_->LockNVSpace(
        index, true /* lock_read */, false /* lock_write */,
        using_owner_authorization, authorization);
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result);
      return MapTpmError(result);
    }
  }
  if (lock_write && !is_write_locked) {
    trunks::AuthorizationDelegate* authorization = nullptr;
    std::unique_ptr<trunks::PolicySession> policy_session =
        trunks_factory_.GetPolicySession();
    bool using_owner_authorization = false;
    if (nvram_public.attributes & trunks::TPMA_NV_POLICYWRITE) {
      NvramPolicyRecord policy_record;
      if (!GetPolicyRecord(index, &policy_record)) {
        LOG(ERROR) << "Policy record missing.";
        return NVRAM_RESULT_INVALID_PARAMETER;
      }
      if (!SetupPolicySession(policy_record, authorization_value,
                              trunks::TPM_CC_NV_WriteLock,
                              policy_session.get())) {
        // This will fail if policy is not met, e.g. a PCR value is not the
        // required value.
        return NVRAM_RESULT_ACCESS_DENIED;
      }
      authorization = policy_session->GetDelegate();
    } else if (nvram_public.attributes & trunks::TPMA_NV_AUTHWRITE) {
      trunks_session_->SetEntityAuthorizationValue(authorization_value);
      authorization = trunks_session_->GetDelegate();
    } else if (nvram_public.attributes & trunks::TPMA_NV_OWNERWRITE) {
      if (!SetupOwnerSession()) {
        // The owner password has been destroyed.
        return NVRAM_RESULT_OPERATION_DISABLED;
      }
      using_owner_authorization = true;
      authorization = trunks_session_->GetDelegate();
    } else {
      // TPMA_NV_PPWRITE: Platform authorization is long gone.
      return NVRAM_RESULT_OPERATION_DISABLED;
    }
    result = trunks_utility_->LockNVSpace(
        index, false /* lock_read */, true /* lock_write */,
        using_owner_authorization, authorization);
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result);
      return MapTpmError(result);
    }
  }
  return NVRAM_RESULT_SUCCESS;
}

NvramResult Tpm2NvramImpl::ListSpaces(std::vector<uint32_t>* index_list) {
  return MapTpmError(trunks_utility_->ListNVSpaces(index_list));
}

NvramResult Tpm2NvramImpl::GetSpaceInfo(
    uint32_t index,
    size_t* size,
    bool* is_read_locked,
    bool* is_write_locked,
    std::vector<NvramSpaceAttribute>* attributes,
    NvramSpacePolicy* policy) {
  trunks::TPMS_NV_PUBLIC nvram_public;
  TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading NV space for index " << index
               << " with error: " << GetErrorString(result);
    return MapTpmError(result);
  }
  *size = nvram_public.data_size;
  *is_read_locked =
      ((nvram_public.attributes & trunks::TPMA_NV_READLOCKED) != 0);
  *is_write_locked =
      ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0);
  MapAttributesFromTpm(nvram_public.attributes, attributes);
  *policy = NVRAM_POLICY_NONE;
  NvramPolicyRecord policy_record;
  if (GetPolicyRecord(index, &policy_record)) {
    *policy = policy_record.policy();
    if (!policy_record.world_read_allowed()) {
      attributes->push_back(NVRAM_READ_AUTHORIZATION);
    }
    if (!policy_record.world_write_allowed()) {
      attributes->push_back(NVRAM_WRITE_AUTHORIZATION);
    }
  }
  return NVRAM_RESULT_SUCCESS;
}

bool Tpm2NvramImpl::Initialize() {
#ifndef TRUNKS_USE_PER_OP_SESSIONS
  if (initialized_) {
    return true;
  }
  TPM_RC result =
      trunks_session_->StartUnboundSession(true /* salted */,
                                           true /* enable_encryption */);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting a default authorization session: "
               << GetErrorString(result);
    return false;
  }
  initialized_ = true;
#endif
  return true;
}

std::string Tpm2NvramImpl::GetOwnerPassword() {
  LocalData local_data;
  if (local_data_store_ && local_data_store_->Read(&local_data)) {
    return local_data.owner_password();
  }
  LOG(ERROR) << "TPM owner password requested but not available.";
  return std::string();
}

bool Tpm2NvramImpl::SetupOwnerSession() {
  // TODO(menghuan): support Pre-Own password?
  std::string owner_password = GetOwnerPassword();
  if (owner_password.empty()) {
    LOG(ERROR) << "Owner authorization required but not available.";
    return false;
  }
  trunks_session_->SetEntityAuthorizationValue(owner_password);
  return true;
}

bool Tpm2NvramImpl::SetupPolicySession(
    const NvramPolicyRecord& policy_record,
    const std::string& authorization_value,
    trunks::TPM_CC command_code,
    trunks::PolicySession* session) {
  TPM_RC result = session->StartUnboundSession(true /* salted */,
                                               true /* enable_encryption */);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting a policy authorization session: "
               << GetErrorString(result);
    return false;
  }
  session->SetEntityAuthorizationValue(authorization_value);
  if (policy_record.policy() != NVRAM_POLICY_NONE) {
    if (!AddPoliciesForCommand(policy_record, command_code, session)) {
      return false;
    }
    if (!AddPolicyOR(policy_record, session)) {
      return false;
    }
  }
  return true;
}

bool Tpm2NvramImpl::AddPoliciesForCommand(
    const NvramPolicyRecord& policy_record,
    trunks::TPM_CC command_code,
    trunks::PolicySession* session) {
  TPM_RC result = session->PolicyCommandCode(command_code);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Failed to setup command code policy.";
    return false;
  }
  bool is_write_command = (command_code == trunks::TPM_CC_NV_Write ||
                           command_code == trunks::TPM_CC_NV_WriteLock ||
                           command_code == trunks::TPM_CC_NV_Extend);
  bool is_read_command = !is_write_command;
  // Check if this operation requires an authorization value.
  if ((is_read_command && !policy_record.world_read_allowed()) ||
      (is_write_command && !policy_record.world_write_allowed())) {
    result = session->PolicyAuthValue();
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Failed to setup auth policy.";
      return false;
    }
  }
  if (policy_record.policy() == NVRAM_POLICY_PCR0) {
    std::string current_pcr_value;
    result = trunks_utility_->ReadPCR(0, &current_pcr_value);
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Failed to read the current PCR value.";
      return false;
    }
    result = session->PolicyPCR(
        std::map<uint32_t, std::string>({{0, current_pcr_value}}));
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Failed to setup PCR policy.";
      return false;
    }
  }
  return true;
}

bool Tpm2NvramImpl::AddPolicyOR(
    const NvramPolicyRecord& policy_record,
    trunks::PolicySession* session) {
  std::vector<std::string> digests;
  for (int i = 0; i < policy_record.policy_digests_size(); ++i) {
    digests.push_back(policy_record.policy_digests(i));
  }
  TPM_RC result = session->PolicyOR(digests);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Failed to setup OR policy.";
    return false;
  }
  return true;
}

bool Tpm2NvramImpl::ComputePolicyDigest(NvramPolicyRecord* policy_record,
                                        std::string* digest) {
  if (policy_record->policy() == NVRAM_POLICY_NONE) {
    digest->clear();
    return true;
  }
  // Compute a policy digest for each command then OR them all together. This
  // approach gives flexibility to have different requirements for read and
  // write operations, and the ability to support authorization values combined
  // with other policies.
  std::unique_ptr<trunks::PolicySession> trial_session;
  for (trunks::TPM_CC command_code :
       {trunks::TPM_CC_NV_Extend, trunks::TPM_CC_NV_Write,
        trunks::TPM_CC_NV_WriteLock, trunks::TPM_CC_NV_Read,
        trunks::TPM_CC_NV_ReadLock, trunks::TPM_CC_NV_Certify}) {
    trial_session = trunks_factory_.GetTrialSession();
    if (trial_session->StartUnboundSession(true /* salted */,
                                           false /* enable_encryption */) !=
        TPM_RC_SUCCESS) {
      return false;
    }
    if (!AddPoliciesForCommand(*policy_record, command_code,
                               trial_session.get())) {
      return false;
    }
    if (trial_session->GetDigest(digest) != TPM_RC_SUCCESS) {
      return false;
    }
    policy_record->add_policy_digests(*digest);
  }
  if (!AddPolicyOR(*policy_record, trial_session.get())) {
    return false;
  }
  if (trial_session->GetDigest(digest) != TPM_RC_SUCCESS) {
    return false;
  }
  return true;
}

bool Tpm2NvramImpl::GetPolicyRecord(uint32_t index, NvramPolicyRecord* record) {
  LocalData local_data;
  if (local_data_store_ && local_data_store_->Read(&local_data)) {
    for (int i = 0; i < local_data.nvram_policy_size(); ++i) {
      if (local_data.nvram_policy(i).index() == index) {
        *record = local_data.nvram_policy(i);
        return true;
      }
    }
  }
  return false;
}

bool Tpm2NvramImpl::SavePolicyRecord(const NvramPolicyRecord& record) {
  LocalData local_data;
  if (!local_data_store_ || !local_data_store_->Read(&local_data)) {
    LOG(ERROR) << "Failed to read local data.";
    return false;
  }
  LocalData new_local_data = local_data;
  new_local_data.clear_nvram_policy();
  for (int i = 0; i < local_data.nvram_policy_size(); ++i) {
    // Keep only the ones that don't match |record|.
    if (local_data.nvram_policy(i).index() != record.index()) {
      *new_local_data.add_nvram_policy() = local_data.nvram_policy(i);
    }
  }
  *new_local_data.add_nvram_policy() = record;
  if (!local_data_store_->Write(new_local_data)) {
    LOG(ERROR) << "Failed to write local data.";
    return false;
  }
  return true;
}

void Tpm2NvramImpl::DeletePolicyRecord(uint32_t index) {
  LocalData local_data;
  if (local_data_store_ && local_data_store_->Read(&local_data)) {
    LocalData new_local_data = local_data;
    new_local_data.clear_nvram_policy();
    for (int i = 0; i < local_data.nvram_policy_size(); ++i) {
      // Keep only the ones that don't match |index|.
      if (local_data.nvram_policy(i).index() != index) {
        *new_local_data.add_nvram_policy() = local_data.nvram_policy(i);
      }
    }
    local_data_store_->Write(new_local_data);
  }
}

}  // namespace tpm_manager
