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

#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <vector>

#include <base/callback.h>

#include "trunks/error_codes.h"

namespace {

const int kMaxCommandAttempts = 3;
const size_t kMinimumAuthorizationSize = 9;
const size_t kMessageHeaderSize = 10;
const trunks::TPM_HANDLE kMaxVirtualHandle =
    (trunks::HR_TRANSIENT + trunks::HR_HANDLE_MASK);

class ScopedBool {
 public:
  ScopedBool() : target_(nullptr) {}
  ~ScopedBool() {
    if (target_) {
      *target_ = false;
    }
  }
  void Enable(bool* target) {
    target_ = target;
    *target_ = true;
  }

 private:
  bool* target_;
};

}  // namespace

namespace trunks {

ResourceManager::ResourceManager(const TrunksFactory& factory,
                                 CommandTransceiver* next_transceiver)
    : factory_(factory), next_transceiver_(next_transceiver) {}

ResourceManager::~ResourceManager() {}

void ResourceManager::Initialize() {
  // Abort if the TPM is not in a reasonable state and we can't get it into one.
  std::unique_ptr<TpmUtility> tpm_utility = factory_.GetTpmUtility();
  CHECK_EQ(tpm_utility->Startup(), TPM_RC_SUCCESS);
  CHECK_EQ(tpm_utility->InitializeTpm(), TPM_RC_SUCCESS);
  // Full control of the TPM is assumed and required. Existing transient object
  // and session handles are mercilessly flushed.
  for (UINT32 handle_type :
       {HR_TRANSIENT, HR_HMAC_SESSION, HR_POLICY_SESSION}) {
    TPMI_YES_NO more_data = YES;
    TPMS_CAPABILITY_DATA data;
    UINT32 handle_range = handle_type;
    while (more_data) {
      TPM_RC result = factory_.GetTpm()->GetCapabilitySync(
          TPM_CAP_HANDLES, handle_range, MAX_CAP_HANDLES, &more_data, &data,
          nullptr);
      if (result != TPM_RC_SUCCESS) {
        LOG(WARNING) << "Failed to query existing handles: "
                     << GetErrorString(result);
        break;
      }
      const TPML_HANDLE& handle_list = data.data.handles;
      for (UINT32 i = 0; i < handle_list.count; ++i) {
        factory_.GetTpm()->FlushContextSync(handle_list.handle[i], nullptr);
      }
      if (more_data) {
        // Adjust the range to be greater than the most recent handle so on the
        // next query we'll start where we left off.
        handle_range = handle_list.handle[handle_list.count - 1];
      }
    }
  }
}

void ResourceManager::SendCommand(const std::string& command,
                                  const ResponseCallback& callback) {
  callback.Run(SendCommandAndWait(command));
}

std::string ResourceManager::SendCommandAndWait(const std::string& command) {
  // Sanitize the |command|. If this succeeds consistency of the command header
  // and the size of all other sections can be assumed.
  MessageInfo command_info;
  TPM_RC result = ParseCommand(command, &command_info);
  if (result != TPM_RC_SUCCESS) {
    return CreateErrorResponse(result);
  }
  // A special case for FlushContext. It requires special handling because it
  // has a handle as a parameter and because we need to cleanup if it succeeds.
  if (command_info.code == TPM_CC_FlushContext) {
    return ProcessFlushContext(command, command_info);
  }
  // Process all the input handles, e.g. map virtual handles.
  std::vector<TPM_HANDLE> updated_handles;
  for (auto handle : command_info.handles) {
    TPM_HANDLE tpm_handle;
    result = ProcessInputHandle(command_info, handle, &tpm_handle);
    if (result != TPM_RC_SUCCESS) {
      return CreateErrorResponse(result);
    }
    updated_handles.push_back(tpm_handle);
  }
  std::string updated_command = ReplaceHandles(command, updated_handles);
  // Make sure all the required sessions are loaded.
  for (auto handle : command_info.session_handles) {
    result = EnsureSessionIsLoaded(command_info, handle);
    if (result != TPM_RC_SUCCESS) {
      return CreateErrorResponse(result);
    }
  }
  // On a ContextLoad we may need to map virtualized context data.
  if (command_info.code == TPM_CC_ContextLoad) {
    std::string actual_load_data =
        GetActualContextFromExternalContext(command_info.parameter_data);
    // Check equality to see if replacement is necessary, and check size to see
    // if the command looks like we expect (the idea is to avoid 'fixing'
    // malformed commands). Note: updated_command.size() is guaranteed to be >=
    // kMessageHeaderSize based on the sanitization in ParseCommand.
    if (actual_load_data != command_info.parameter_data &&
        actual_load_data.size() ==
            updated_command.size() - kMessageHeaderSize) {
      // Replace the parameter section of the command with |actual_load_data|.
      VLOG(1) << "REPLACE_EXTERNAL_CONTEXT";
      updated_command.replace(kMessageHeaderSize, std::string::npos,
                              actual_load_data);
    }
  }
  // Send the |updated_command| to the next layer. Attempt to fix any actionable
  // warnings for up to kMaxCommandAttempts.
  std::string response;
  MessageInfo response_info;
  int attempts = 0;
  while (attempts++ < kMaxCommandAttempts) {
    response = next_transceiver_->SendCommandAndWait(updated_command);
    result = ParseResponse(command_info, response, &response_info);
    if (result != TPM_RC_SUCCESS) {
      return CreateErrorResponse(result);
    }
    if (!FixWarnings(command_info, response_info.code)) {
      // No actionable warnings were handled.
      break;
    }
  }
  if (response_info.code == TPM_RC_SUCCESS) {
    if (response_info.session_continued.size() !=
        command_info.session_handles.size()) {
      LOG(WARNING) << "Session count mismatch!";
    }
    // Cleanup any sessions that were not continued.
    for (size_t i = 0; i < command_info.session_handles.size(); ++i) {
      if (i < response_info.session_continued.size() &&
          !response_info.session_continued[i]) {
        CleanupFlushedHandle(command_info.session_handles[i]);
      }
    }
    // On a successful context save we need to cache the context data in case it
    // needs to be virtualized later.
    if (command_info.code == TPM_CC_ContextSave) {
      ProcessExternalContextSave(command_info, response_info);
    }
    // Process all the output handles, which is loosely the inverse of the input
    // handle processing. E.g. virtualize handles.
    std::vector<TPM_HANDLE> virtual_handles;
    for (auto handle : response_info.handles) {
      virtual_handles.push_back(ProcessOutputHandle(handle));
    }
    response = ReplaceHandles(response, virtual_handles);
  }
  return response;
}

bool ResourceManager::ChooseSessionToEvict(
    const std::vector<TPM_HANDLE>& sessions_to_retain,
    TPM_HANDLE* session_to_evict) {
  // Build a list of candidates by excluding |sessions_to_retain|.
  std::vector<TPM_HANDLE> candidates;
  for (auto& item : session_handles_) {
    HandleInfo& info = item.second;
    if (info.is_loaded &&
        std::find(sessions_to_retain.begin(), sessions_to_retain.end(),
                  info.tpm_handle) == sessions_to_retain.end()) {
      candidates.push_back(item.first);
    }
  }
  if (candidates.empty()) {
    LOG(WARNING) << "No sessions to evict.";
    return false;
  }
  // Choose the candidate with the earliest |time_of_last_use|.
  auto oldest_iter = std::min_element(
      candidates.begin(), candidates.end(), [this](TPM_HANDLE a, TPM_HANDLE b) {
        return (session_handles_[a].time_of_last_use <
                session_handles_[b].time_of_last_use);
      });
  *session_to_evict = *oldest_iter;
  return true;
}

void ResourceManager::CleanupFlushedHandle(TPM_HANDLE flushed_handle) {
  if (IsObjectHandle(flushed_handle)) {
    // For transient object handles, remove both the actual and virtual handles.
    if (virtual_object_handles_.count(flushed_handle) > 0) {
      tpm_object_handles_.erase(
          virtual_object_handles_[flushed_handle].tpm_handle);
      virtual_object_handles_.erase(flushed_handle);
    }
  } else if (IsSessionHandle(flushed_handle)) {
    auto iter = session_handles_.find(flushed_handle);
    if (iter == session_handles_.end()) {
      return;
    }
    // For session handles, remove the handle and any associated context data.
    HandleInfo& info = iter->second;
    if (!info.is_loaded) {
      std::string actual_context_data;
      Serialize_TPMS_CONTEXT(info.context, &actual_context_data);
      if (actual_context_to_external_.count(actual_context_data) > 0) {
        external_context_to_actual_.erase(
            actual_context_to_external_[actual_context_data]);
        actual_context_to_external_.erase(actual_context_data);
      }
    }
    session_handles_.erase(flushed_handle);
    VLOG(1) << "CLEANUP_SESSION: " << std::hex << flushed_handle;
  }
}

TPM_HANDLE ResourceManager::CreateVirtualHandle() {
  TPM_HANDLE handle;
  do {
    handle = next_virtual_handle_;
    if (next_virtual_handle_ == kMaxVirtualHandle) {
      next_virtual_handle_ = TRANSIENT_FIRST;
    } else {
      ++next_virtual_handle_;
    }
  } while (virtual_object_handles_.count(handle) > 0);
  return handle;
}

TPM_RC ResourceManager::EnsureSessionIsLoaded(const MessageInfo& command_info,
                                              TPM_HANDLE session_handle) {
  // A password authorization can skip all this.
  if (session_handle == TPM_RS_PW) {
    return TPM_RC_SUCCESS;
  }
  auto handle_iter = session_handles_.find(session_handle);
  if (handle_iter == session_handles_.end()) {
    return MakeError(TPM_RC_HANDLE, FROM_HERE);
  }
  HandleInfo& handle_info = handle_iter->second;
  if (!handle_info.is_loaded) {
    TPM_RC result = LoadContext(command_info, &handle_info);
    if (result != TPM_RC_SUCCESS) {
      return result;
    }
    VLOG(1) << "RELOAD_SESSION: " << std::hex << session_handle;
  }
  handle_info.time_of_last_use = base::TimeTicks::Now();
  return TPM_RC_SUCCESS;
}

void ResourceManager::EvictObjects(const MessageInfo& command_info) {
  for (auto& item : virtual_object_handles_) {
    HandleInfo& info = item.second;
    if (!info.is_loaded ||
        std::find(command_info.handles.begin(), command_info.handles.end(),
                  item.first) != command_info.handles.end()) {
      continue;
    }
    TPM_RC result = SaveContext(command_info, &info);
    if (result != TPM_RC_SUCCESS) {
      LOG(WARNING) << "Failed to save transient object: "
                   << GetErrorString(result);
      continue;
    }
    result = factory_.GetTpm()->FlushContextSync(info.tpm_handle, nullptr);
    if (result != TPM_RC_SUCCESS) {
      LOG(WARNING) << "Failed to evict transient object: "
                   << GetErrorString(result);
      continue;
    }
    tpm_object_handles_.erase(info.tpm_handle);
    VLOG(1) << "EVICT_OBJECT: " << std::hex << info.tpm_handle;
  }
}

void ResourceManager::EvictSession(const MessageInfo& command_info) {
  TPM_HANDLE session_to_evict;
  if (!ChooseSessionToEvict(command_info.session_handles, &session_to_evict)) {
    return;
  }
  HandleInfo& info = session_handles_[session_to_evict];
  TPM_RC result = SaveContext(command_info, &info);
  if (result != TPM_RC_SUCCESS) {
    LOG(WARNING) << "Failed to evict session: " << GetErrorString(result);
  }
  VLOG(1) << "EVICT_SESSION: " << std::hex << session_to_evict;
}

std::vector<TPM_HANDLE> ResourceManager::ExtractHandlesFromBuffer(
    size_t number_of_handles,
    std::string* buffer) {
  std::vector<TPM_HANDLE> handles(number_of_handles);
  for (size_t i = 0; i < number_of_handles; ++i) {
    TPM_HANDLE handle;
    if (TPM_RC_SUCCESS == Parse_TPM_HANDLE(buffer, &handle, nullptr)) {
      handles[i] = handle;
    }
  }
  return handles;
}

void ResourceManager::FixContextGap(const MessageInfo& command_info) {
  std::vector<TPM_HANDLE> sessions_to_ungap;
  for (const auto& item : session_handles_) {
    const HandleInfo& info = item.second;
    if (!info.is_loaded) {
      sessions_to_ungap.push_back(item.first);
    }
  }
  // Sort by |time_of_create|.
  std::sort(sessions_to_ungap.begin(), sessions_to_ungap.end(),
            [this](TPM_HANDLE a, TPM_HANDLE b) {
              return (session_handles_[a].time_of_create <
                      session_handles_[b].time_of_create);
            });
  for (auto handle : sessions_to_ungap) {
    HandleInfo& info = session_handles_[handle];
    // Loading and re-saving allows the TPM to assign a new context counter.
    std::string old_context_blob;
    Serialize_TPMS_CONTEXT(info.context, &old_context_blob);
    TPM_RC result = LoadContext(command_info, &info);
    if (result != TPM_RC_SUCCESS) {
      LOG(WARNING) << "Failed to un-gap session (load): "
                   << GetErrorString(result);
      continue;
    }
    result = SaveContext(command_info, &info);
    if (result != TPM_RC_SUCCESS) {
      LOG(WARNING) << "Failed to un-gap session (save): "
                   << GetErrorString(result);
      continue;
    }
    // If this context is one that we're tracking for external use, update it.
    auto iter = actual_context_to_external_.find(old_context_blob);
    if (iter == actual_context_to_external_.end()) {
      continue;
    }
    std::string new_context_blob;
    Serialize_TPMS_CONTEXT(info.context, &new_context_blob);
    const std::string& external_context_blob = iter->second;
    actual_context_to_external_[new_context_blob] = external_context_blob;
    external_context_to_actual_[external_context_blob] = new_context_blob;
    actual_context_to_external_.erase(old_context_blob);
  }
}

bool ResourceManager::FixWarnings(const MessageInfo& command_info,
                                  TPM_RC result) {
  if ((result & RC_WARN) == 0) {
    return false;
  }
  // This method can be called anytime without tracking whether the current
  // operation is already an attempt to fix a warning. All re-entrance issues
  // are dealt with here using the following rule: Never attempt to fix the same
  // warning twice.
  ScopedBool scoped_bool;
  if (!fixing_warnings_) {
    scoped_bool.Enable(&fixing_warnings_);
    warnings_already_seen_.clear();
  } else if (warnings_already_seen_.count(result) > 0) {
    return false;
  }
  warnings_already_seen_.insert(result);
  switch (result) {
    case TPM_RC_CONTEXT_GAP:
      FixContextGap(command_info);
      return true;
    case TPM_RC_OBJECT_MEMORY:
    case TPM_RC_OBJECT_HANDLES:
      EvictObjects(command_info);
      return true;
    case TPM_RC_SESSION_MEMORY:
      EvictSession(command_info);
      return true;
    case TPM_RC_MEMORY:
      EvictObjects(command_info);
      EvictSession(command_info);
      return true;
    case TPM_RC_SESSION_HANDLES:
      FlushSession(command_info);
      return true;
  }
  return false;
}

void ResourceManager::FlushSession(const MessageInfo& command_info) {
  TPM_HANDLE session_to_flush;
  LOG(WARNING) << "Resource manager needs to flush a session.";
  if (!ChooseSessionToEvict(command_info.session_handles, &session_to_flush)) {
    return;
  }
  TPM_RC result =
      factory_.GetTpm()->FlushContextSync(session_to_flush, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(WARNING) << "Failed to flush session: " << GetErrorString(result);
    return;
  }
  CleanupFlushedHandle(session_to_flush);
}

std::string ResourceManager::GetActualContextFromExternalContext(
    const std::string& external_context) {
  auto iter = external_context_to_actual_.find(external_context);
  if (iter == external_context_to_actual_.end()) {
    return external_context;
  }
  return iter->second;
}

bool ResourceManager::IsObjectHandle(TPM_HANDLE handle) const {
  return ((handle & HR_RANGE_MASK) == HR_TRANSIENT);
}

bool ResourceManager::IsSessionHandle(TPM_HANDLE handle) const {
  return ((handle & HR_RANGE_MASK) == HR_HMAC_SESSION ||
          (handle & HR_RANGE_MASK) == HR_POLICY_SESSION);
}

TPM_RC ResourceManager::LoadContext(const MessageInfo& command_info,
                                    HandleInfo* handle_info) {
  CHECK(!handle_info->is_loaded);
  TPM_RC result = TPM_RC_SUCCESS;
  int attempts = 0;
  while (attempts++ < kMaxCommandAttempts) {
    result = factory_.GetTpm()->ContextLoadSync(
        handle_info->context, &handle_info->tpm_handle, nullptr);
    if (!FixWarnings(command_info, result)) {
      break;
    }
  }
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << __func__
               << ": Failed to load context: " << GetErrorString(result);
    return result;
  }
  handle_info->is_loaded = true;
  return result;
}

TPM_RC ResourceManager::MakeError(TPM_RC tpm_error,
                                  const ::tracked_objects::Location& location) {
  LOG(ERROR) << "ResourceManager::" << location.function_name() << ":"
             << location.line_number() << ": " << GetErrorString(tpm_error);
  return tpm_error + kResourceManagerTpmErrorBase;
}

TPM_RC ResourceManager::ParseCommand(const std::string& command,
                                     MessageInfo* command_info) {
  CHECK(command_info);
  std::string buffer = command;
  TPM_ST tag;
  TPM_RC result = Parse_TPM_ST(&buffer, &tag, nullptr);
  if (result != TPM_RC_SUCCESS) {
    return MakeError(result, FROM_HERE);
  }
  if (tag != TPM_ST_SESSIONS && tag != TPM_ST_NO_SESSIONS) {
    return MakeError(TPM_RC_TAG, FROM_HERE);
  }
  command_info->has_sessions = (tag == TPM_ST_SESSIONS);

  UINT32 size = 0;
  result = Parse_UINT32(&buffer, &size, nullptr);
  if (result != TPM_RC_SUCCESS) {
    return MakeError(result, FROM_HERE);
  }
  if (size != command.size()) {
    return MakeError(TPM_RC_SIZE, FROM_HERE);
  }

  result = Parse_TPM_CC(&buffer, &command_info->code, nullptr);
  if (result != TPM_RC_SUCCESS) {
    return MakeError(result, FROM_HERE);
  }
  if (command_info->code < TPM_CC_FIRST || command_info->code > TPM_CC_LAST) {
    return MakeError(TPM_RC_COMMAND_CODE, FROM_HERE);
  }

  size_t number_of_handles = GetNumberOfRequestHandles(command_info->code);
  command_info->handles = ExtractHandlesFromBuffer(number_of_handles, &buffer);
  if (number_of_handles != command_info->handles.size()) {
    return MakeError(TPM_RC_SIZE, FROM_HERE);
  }
  if (command_info->has_sessions) {
    // Sessions exist, so we're expecting a valid authorization size value.
    UINT32 authorization_size = 0;
    result = Parse_UINT32(&buffer, &authorization_size, nullptr);
    if (result != TPM_RC_SUCCESS) {
      return MakeError(result, FROM_HERE);
    }
    if (buffer.size() < authorization_size ||
        authorization_size < kMinimumAuthorizationSize) {
      return MakeError(TPM_RC_SIZE, FROM_HERE);
    }
    // Move out the parameter bytes, leaving only the authorization section.
    command_info->parameter_data = buffer.substr(authorization_size);
    buffer.erase(authorization_size);
    // Parse as many authorization sessions as there are in the section.
    while (!buffer.empty()) {
      TPM_HANDLE handle;
      result = Parse_TPM_HANDLE(&buffer, &handle, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      if (handle != TPM_RS_PW && session_handles_.count(handle) == 0) {
        return MakeError(TPM_RC_HANDLE, FROM_HERE);
      }
      TPM2B_NONCE nonce;
      result = Parse_TPM2B_NONCE(&buffer, &nonce, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      BYTE attributes;
      result = Parse_BYTE(&buffer, &attributes, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      TPM2B_DIGEST authorization;
      result = Parse_TPM2B_DIGEST(&buffer, &authorization, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      command_info->session_handles.push_back(handle);
      command_info->session_continued.push_back((attributes & 1) == 1);
    }
  } else {
    // No sessions, so all remaining data is parameter data.
    command_info->parameter_data = buffer;
  }
  return TPM_RC_SUCCESS;
}

TPM_RC ResourceManager::ParseResponse(const MessageInfo& command_info,
                                      const std::string& response,
                                      MessageInfo* response_info) {
  CHECK(response_info);
  std::string buffer = response;
  TPM_ST tag;
  TPM_RC result = Parse_TPM_ST(&buffer, &tag, nullptr);
  if (result != TPM_RC_SUCCESS) {
    return MakeError(result, FROM_HERE);
  }
  if (tag != TPM_ST_SESSIONS && tag != TPM_ST_NO_SESSIONS) {
    return MakeError(TPM_RC_TAG, FROM_HERE);
  }
  response_info->has_sessions = (tag == TPM_ST_SESSIONS);

  UINT32 size = 0;
  result = Parse_UINT32(&buffer, &size, nullptr);
  if (result != TPM_RC_SUCCESS) {
    return MakeError(result, FROM_HERE);
  }
  if (size != response.size()) {
    return MakeError(TPM_RC_SIZE, FROM_HERE);
  }

  result = Parse_TPM_RC(&buffer, &response_info->code, nullptr);
  if (result != TPM_RC_SUCCESS) {
    return MakeError(result, FROM_HERE);
  }

  size_t number_of_handles = GetNumberOfResponseHandles(command_info.code);
  response_info->handles = ExtractHandlesFromBuffer(number_of_handles, &buffer);
  if (number_of_handles != response_info->handles.size()) {
    return MakeError(TPM_RC_SIZE, FROM_HERE);
  }
  if (response_info->has_sessions) {
    // Sessions exist, so we're expecting a valid parameter size value.
    UINT32 parameter_size = 0;
    result = Parse_UINT32(&buffer, &parameter_size, nullptr);
    if (result != TPM_RC_SUCCESS) {
      return MakeError(result, FROM_HERE);
    }
    if (buffer.size() < parameter_size) {
      return MakeError(TPM_RC_SIZE, FROM_HERE);
    }
    // Move out the parameter bytes, leaving only the authorization section.
    response_info->parameter_data = buffer.substr(0, parameter_size);
    buffer.erase(0, parameter_size);
    // Parse as many authorization sessions as there are in the section.
    while (!buffer.empty()) {
      TPM2B_NONCE nonce;
      result = Parse_TPM2B_NONCE(&buffer, &nonce, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      BYTE attributes;
      result = Parse_BYTE(&buffer, &attributes, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      TPM2B_DIGEST acknowledgement;
      result = Parse_TPM2B_DIGEST(&buffer, &acknowledgement, nullptr);
      if (result != TPM_RC_SUCCESS) {
        return MakeError(result, FROM_HERE);
      }
      response_info->session_continued.push_back((attributes & 1) == 1);
    }
  } else {
    // No sessions, so all remaining data is parameter data.
    response_info->parameter_data = buffer;
  }
  return TPM_RC_SUCCESS;
}

void ResourceManager::ProcessExternalContextSave(
    const MessageInfo& command_info,
    const MessageInfo& response_info) {
  CHECK_EQ(command_info.code, TPM_CC_ContextSave);
  if (command_info.handles.size() != 1) {
    LOG(WARNING) << "Invalid context save command.";
    return;
  }
  // We know command_info.handles[0] is valid because this is validated when the
  // command is parsed.
  TPM_HANDLE saved_handle = command_info.handles[0];
  // Only track external context data for session handles.
  if (!IsSessionHandle(saved_handle)) {
    return;
  }
  std::string mutable_parameter = response_info.parameter_data;
  TPMS_CONTEXT context;
  std::string context_blob;
  TPM_RC result =
      Parse_TPMS_CONTEXT(&mutable_parameter, &context, &context_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(WARNING) << "Invalid context save response: " << GetErrorString(result);
    return;
  }
  auto iter = session_handles_.find(saved_handle);
  if (iter != session_handles_.end()) {
    iter->second.is_loaded = false;
    iter->second.context = context;
  } else {
    // Unknown handle? Not anymore.
    LOG(WARNING) << "Context for unknown handle.";
    HandleInfo new_handle_info;
    new_handle_info.Init(saved_handle);
    new_handle_info.is_loaded = false;
    new_handle_info.context = context;
    session_handles_[saved_handle] = new_handle_info;
  }
  // Use the original context data as the 'external' context data. If this gets
  // virtualized, only the 'actual' context data will change.
  external_context_to_actual_[context_blob] = context_blob;
  actual_context_to_external_[context_blob] = context_blob;
}

std::string ResourceManager::ProcessFlushContext(
    const std::string& command,
    const MessageInfo& command_info) {
  std::string buffer = command_info.parameter_data;
  // There must be exactly one handle in the parameters section.
  std::vector<TPM_HANDLE> handles = ExtractHandlesFromBuffer(1, &buffer);
  if (handles.size() != 1) {
    return CreateErrorResponse(MakeError(TPM_RC_SIZE, FROM_HERE));
  }
  TPM_HANDLE handle = handles[0];
  TPM_HANDLE actual_handle = handle;
  if (IsObjectHandle(handle)) {
    auto iter = virtual_object_handles_.find(handle);
    if (iter == virtual_object_handles_.end()) {
      return CreateErrorResponse(MakeError(TPM_RC_HANDLE, FROM_HERE));
    }
    if (!iter->second.is_loaded) {
      // The handle wasn't loaded so no need to bother the TPM.
      CleanupFlushedHandle(handle);
      return CreateErrorResponse(TPM_RC_SUCCESS);
    }
    actual_handle = iter->second.tpm_handle;
  }
  // Send a command with the original header but with |actual_handle| as the
  // parameter.
  std::string handle_blob;
  Serialize_TPM_HANDLE(actual_handle, &handle_blob);
  std::string updated_command =
      command.substr(0, kMessageHeaderSize) + handle_blob;
  // No need to loop and fix warnings, there are no actionable warnings on when
  // flushing context.
  std::string response = next_transceiver_->SendCommandAndWait(updated_command);
  MessageInfo response_info;
  TPM_RC result = ParseResponse(command_info, response, &response_info);
  if (result != TPM_RC_SUCCESS) {
    return CreateErrorResponse(result);
  }
  // Cleanup the handle locally even if the TPM did not recognize it.
  if (response_info.code == TPM_RC_SUCCESS ||
      response_info.code == TPM_RC_HANDLE) {
    CleanupFlushedHandle(handle);
  }
  return response;
}

TPM_RC ResourceManager::ProcessInputHandle(const MessageInfo& command_info,
                                           TPM_HANDLE virtual_handle,
                                           TPM_HANDLE* actual_handle) {
  // Only transient object handles are virtualized.
  if (!IsObjectHandle(virtual_handle)) {
    *actual_handle = virtual_handle;
    return TPM_RC_SUCCESS;
  }
  auto handle_iter = virtual_object_handles_.find(virtual_handle);
  if (handle_iter == virtual_object_handles_.end()) {
    return MakeError(TPM_RC_HANDLE, FROM_HERE);
  }
  HandleInfo& handle_info = handle_iter->second;
  if (!handle_info.is_loaded) {
    TPM_RC result = LoadContext(command_info, &handle_info);
    if (result != TPM_RC_SUCCESS) {
      return result;
    }
    tpm_object_handles_[handle_info.tpm_handle] = virtual_handle;
    VLOG(1) << "RELOAD_OBJECT: " << std::hex << virtual_handle;
  }
  VLOG(1) << "INPUT_HANDLE_REPLACE: " << std::hex << virtual_handle << " -> "
          << std::hex << handle_info.tpm_handle;
  *actual_handle = handle_info.tpm_handle;
  return TPM_RC_SUCCESS;
}

TPM_HANDLE ResourceManager::ProcessOutputHandle(TPM_HANDLE handle) {
  // Track, but do not virtualize, session handles.
  if (IsSessionHandle(handle)) {
    auto session_handle_iter = session_handles_.find(handle);
    if (session_handle_iter == session_handles_.end()) {
      HandleInfo new_handle_info;
      new_handle_info.Init(handle);
      session_handles_[handle] = new_handle_info;
      VLOG(1) << "OUTPUT_HANDLE_NEW_SESSION: " << std::hex << handle;
    }
    return handle;
  }
  // Only transient object handles are virtualized.
  if (!IsObjectHandle(handle)) {
    return handle;
  }
  auto virtual_handle_iter = tpm_object_handles_.find(handle);
  if (virtual_handle_iter == tpm_object_handles_.end()) {
    TPM_HANDLE new_virtual_handle = CreateVirtualHandle();
    HandleInfo new_handle_info;
    new_handle_info.Init(handle);
    virtual_object_handles_[new_virtual_handle] = new_handle_info;
    tpm_object_handles_[handle] = new_virtual_handle;
    VLOG(1) << "OUTPUT_HANDLE_NEW_VIRTUAL: " << std::hex << handle << " -> "
            << std::hex << new_virtual_handle;
    return new_virtual_handle;
  }
  VLOG(1) << "OUTPUT_HANDLE_REPLACE: " << std::hex << handle << " -> "
          << std::hex << virtual_handle_iter->second;
  return virtual_handle_iter->second;
}

std::string ResourceManager::ReplaceHandles(
    const std::string& message,
    const std::vector<TPM_HANDLE>& new_handles) {
  std::string handles_blob;
  for (auto handle : new_handles) {
    CHECK_EQ(Serialize_TPM_HANDLE(handle, &handles_blob), TPM_RC_SUCCESS);
  }
  std::string mutable_message = message;
  CHECK_GE(message.size(), kMessageHeaderSize + handles_blob.size());
  return mutable_message.replace(kMessageHeaderSize, handles_blob.size(),
                                 handles_blob);
}

TPM_RC ResourceManager::SaveContext(const MessageInfo& command_info,
                                    HandleInfo* handle_info) {
  CHECK(handle_info->is_loaded);
  TPM_RC result = TPM_RC_SUCCESS;
  int attempts = 0;
  while (attempts++ < kMaxCommandAttempts) {
    std::string tpm_handle_name;
    Serialize_TPM_HANDLE(handle_info->tpm_handle, &tpm_handle_name);
    result = factory_.GetTpm()->ContextSaveSync(handle_info->tpm_handle,
                                                tpm_handle_name,
                                                &handle_info->context, nullptr);
    if (!FixWarnings(command_info, result)) {
      break;
    }
  }
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << __func__
               << ": Failed to load context: " << GetErrorString(result);
    return result;
  }
  handle_info->is_loaded = false;
  return result;
}

ResourceManager::HandleInfo::HandleInfo() : is_loaded(false), tpm_handle(0) {
  memset(&context, 0, sizeof(TPMS_CONTEXT));
}

void ResourceManager::HandleInfo::Init(TPM_HANDLE handle) {
  tpm_handle = handle;
  is_loaded = true;
  time_of_create = base::TimeTicks::Now();
  time_of_last_use = base::TimeTicks::Now();
}

}  // namespace trunks
