//
// 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/tpm_nvram_impl.h"

#include <arpa/inet.h>

#include <string>

#include <base/logging.h>
#include <base/stl_util.h>
#include <trousers/scoped_tss_type.h>

#include "tpm_manager/common/local_data.pb.h"
#include "tpm_manager/server/local_data_store.h"
#include "tpm_manager/server/tpm_util.h"

namespace {

// PCR0 at locality 1 is used to differentiate between developed and normal
// mode. Restricting nvram to the PCR0 value in locality 1 prevents nvram from
// persisting across mode switch.
const unsigned int kTpmBootPCR = 0;
const unsigned int kTpmPCRLocality = 1;

}  // namespace

namespace tpm_manager {

using trousers::ScopedTssMemory;
using trousers::ScopedTssNvStore;
using trousers::ScopedTssPcrs;

TpmNvramImpl::TpmNvramImpl(LocalDataStore* local_data_store)
    : local_data_store_(local_data_store) {}

bool TpmNvramImpl::DefineNvram(uint32_t index, size_t length) {
  ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
  if (!(InitializeNvramHandle(&nv_handle, index) &&
        SetOwnerPolicy(&nv_handle))) {
    return false;
  }
  TSS_RESULT result;
  result =
      Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_DATASIZE, 0, length);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set size on NVRAM object: " << length;
    return false;
  }
  // Restrict to only one write.
  result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS, 0,
                                TPM_NV_PER_WRITEDEFINE);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set PER_WRITEDEFINE on NVRAM object";
    return false;
  }
  // Restrict to writing only with owner authorization.
  result = Tspi_SetAttribUint32(nv_handle, TSS_TSPATTRIB_NV_PERMISSIONS, 0,
                                TPM_NV_PER_OWNERWRITE);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set PER_OWNERWRITE on NVRAM object";
    return false;
  }
  ScopedTssPcrs pcr_handle(tpm_connection_.GetContext());
  if (!SetCompositePcr0(&pcr_handle)) {
    return false;
  }
  result = Tspi_NV_DefineSpace(nv_handle,
                               pcr_handle /* ReadPCRs restricted to PCR0 */,
                               pcr_handle /* WritePCRs restricted to PCR0 */);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not define NVRAM space: " << index;
    return false;
  }
  return true;
}

bool TpmNvramImpl::DestroyNvram(uint32_t index) {
  bool defined;
  if (!IsNvramDefined(index, &defined)) {
    return false;
  }
  if (!defined) {
    // If the nvram space is not defined, we don't need to destroy it.
    return true;
  }
  ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
  if (!(InitializeNvramHandle(&nv_handle, index) &&
        SetOwnerPolicy(&nv_handle))) {
    return false;
  }
  TSS_RESULT result = Tspi_NV_ReleaseSpace(nv_handle);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not release NVRAM space: " << index;
    return false;
  }
  return true;
}

bool TpmNvramImpl::WriteNvram(uint32_t index, const std::string& data) {
  ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
  if (!(InitializeNvramHandle(&nv_handle, index) &&
        SetOwnerPolicy(&nv_handle))) {
    return false;
  }
  TSS_RESULT result = Tspi_NV_WriteValue(
      nv_handle, 0 /* offset */, data.size(),
      reinterpret_cast<BYTE*>(const_cast<char*>(data.data())));
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not write to NVRAM space: " << index;
    return false;
  }
  return true;
}

bool TpmNvramImpl::ReadNvram(uint32_t index, std::string* data) {
  CHECK(data);
  TSS_RESULT result;
  ScopedTssNvStore nv_handle(tpm_connection_.GetContext());
  if (!InitializeNvramHandle(&nv_handle, index)) {
    return false;
  }
  size_t nvram_size;
  if (!GetNvramSize(index, &nvram_size)) {
    return false;
  }
  data->resize(nvram_size);
  // The Tpm1.2 Specification defines the maximum read size of 128 bytes.
  // Therefore we have to loop through the data returned.
  const size_t kMaxDataSize = 128;
  uint32_t offset = 0;
  while (offset < nvram_size) {
    uint32_t chunk_size = std::max(nvram_size - offset, kMaxDataSize);
    ScopedTssMemory space_data(tpm_connection_.GetContext());
    if ((result = Tspi_NV_ReadValue(nv_handle, offset, &chunk_size,
                                    space_data.ptr()))) {
      TPM_LOG(ERROR, result) << "Could not read from NVRAM space: " << index;
      return false;
    }
    if (!space_data.value()) {
      LOG(ERROR) << "No data read from NVRAM space: " << index;
      return false;
    }
    CHECK_LE((offset + chunk_size), data->size());
    data->replace(offset, chunk_size,
                  reinterpret_cast<char*>(space_data.value()), chunk_size);
    offset += chunk_size;
  }
  return true;
}

bool TpmNvramImpl::IsNvramDefined(uint32_t index, bool* defined) {
  CHECK(defined);
  uint32_t nv_list_data_length = 0;
  ScopedTssMemory nv_list_data(tpm_connection_.GetContext());
  TSS_RESULT result =
      Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_LIST, 0,
                             NULL, &nv_list_data_length, nv_list_data.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
    return false;
  }
  // Walk the list and check if the index exists.
  uint32_t* nv_list = reinterpret_cast<uint32_t*>(nv_list_data.value());
  uint32_t nv_list_length = nv_list_data_length / sizeof(uint32_t);
  index = htonl(index);  // TPM data is network byte order.
  for (uint32_t i = 0; i < nv_list_length; ++i) {
    if (index == nv_list[i]) {
      *defined = true;
      return true;
    }
  }
  *defined = false;
  return true;
}

bool TpmNvramImpl::IsNvramLocked(uint32_t index, bool* locked) {
  CHECK(locked);
  uint32_t nv_index_data_length = 0;
  ScopedTssMemory nv_index_data(tpm_connection_.GetContext());
  TSS_RESULT result =
      Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_INDEX,
                             sizeof(index), reinterpret_cast<BYTE*>(&index),
                             &nv_index_data_length, nv_index_data.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
    return false;
  }
  if (nv_index_data_length < (sizeof(uint32_t) + sizeof(TPM_BOOL))) {
    return false;
  }
  // TPM_NV_DATA_PUBLIC->bWriteDefine is the second to last element in the
  // struct.
  uint32_t* nv_data_public =
      reinterpret_cast<uint32_t*>(nv_index_data.value() + nv_index_data_length -
                                  (sizeof(uint32_t) + sizeof(TPM_BOOL)));
  *locked = (*nv_data_public != 0);
  return true;
}

bool TpmNvramImpl::GetNvramSize(uint32_t index, size_t* size) {
  CHECK(size);
  UINT32 nv_index_data_length = 0;
  ScopedTssMemory nv_index_data(tpm_connection_.GetContext());
  TSS_RESULT result =
      Tspi_TPM_GetCapability(tpm_connection_.GetTpm(), TSS_TPMCAP_NV_INDEX,
                             sizeof(index), reinterpret_cast<BYTE*>(&index),
                             &nv_index_data_length, nv_index_data.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetCapability";
    return false;
  }
  if (nv_index_data_length < sizeof(uint32_t)) {
    return false;
  }
  // TPM_NV_DATA_PUBLIC->dataSize is the last element in the struct.
  uint32_t* nv_data_public = reinterpret_cast<uint32_t*>(
      nv_index_data.value() + nv_index_data_length - sizeof(uint32_t));
  *size = htonl(*nv_data_public);
  return true;
}

bool TpmNvramImpl::InitializeNvramHandle(ScopedTssNvStore* nv_handle,
                                         uint32_t index) {
  TSS_RESULT result = Tspi_Context_CreateObject(
      tpm_connection_.GetContext(), TSS_OBJECT_TYPE_NV, 0, nv_handle->ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not acquire an NVRAM object handle";
    return false;
  }
  result = Tspi_SetAttribUint32(nv_handle->value(), TSS_TSPATTRIB_NV_INDEX, 0,
                                index);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set index on NVRAM object: " << index;
    return false;
  }
  return true;
}

bool TpmNvramImpl::SetOwnerPolicy(ScopedTssNvStore* nv_handle) {
  trousers::ScopedTssPolicy policy_handle(tpm_connection_.GetContext());
  TSS_RESULT result;
  result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
                                     TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
                                     policy_handle.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    return false;
  }
  std::string owner_password;
  if (!GetOwnerPassword(&owner_password)) {
    return false;
  }
  result = Tspi_Policy_SetSecret(
      policy_handle, TSS_SECRET_MODE_PLAIN, owner_password.size(),
      reinterpret_cast<BYTE*>(const_cast<char*>(owner_password.data())));
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    return false;
  }
  result =
      Tspi_Policy_AssignToObject(policy_handle.value(), nv_handle->value());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set NVRAM object policy.";
    return false;
  }
  return true;
}

bool TpmNvramImpl::SetCompositePcr0(ScopedTssPcrs* pcr_handle) {
  TSS_RESULT result = Tspi_Context_CreateObject(
      tpm_connection_.GetContext(), TSS_OBJECT_TYPE_PCRS,
      TSS_PCRS_STRUCT_INFO_SHORT, pcr_handle->ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not acquire PCR object handle";
    return false;
  }
  uint32_t pcr_len;
  std::string owner_password;
  if (!GetOwnerPassword(&owner_password)) {
    return false;
  }
  ScopedTssMemory pcr_value(tpm_connection_.GetContext());
  result = Tspi_TPM_PcrRead(tpm_connection_.GetTpmWithAuth(owner_password),
                            kTpmBootPCR, &pcr_len, pcr_value.ptr());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not read PCR0 value";
    return false;
  }
  result = Tspi_PcrComposite_SetPcrValue(pcr_handle->value(), kTpmBootPCR,
                                         pcr_len, pcr_value.value());
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set value for PCR0 in PCR handle";
    return false;
  }
  result =
      Tspi_PcrComposite_SetPcrLocality(pcr_handle->value(), kTpmPCRLocality);
  if (TPM_ERROR(result)) {
    TPM_LOG(ERROR, result) << "Could not set locality for PCR0 in PCR handle";
    return false;
  }
  return true;
}

bool TpmNvramImpl::GetOwnerPassword(std::string* owner_password) {
  LocalData local_data;
  if (!local_data_store_->Read(&local_data)) {
    LOG(ERROR) << "Error reading local data for owner password.";
    return false;
  }
  if (local_data.owner_password().empty()) {
    LOG(ERROR) << "No owner password present in tpm local_data.";
    return false;
  }
  owner_password->assign(local_data.owner_password());
  return true;
}

}  // namespace tpm_manager
