1bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
2bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Copyright (C) 2015 The Android Open Source Project
3bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
4bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License");
5bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// you may not use this file except in compliance with the License.
6bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// You may obtain a copy of the License at
7bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
8bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//      http://www.apache.org/licenses/LICENSE-2.0
9bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
10bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Unless required by applicable law or agreed to in writing, software
11bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS,
12bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// See the License for the specific language governing permissions and
14bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// limitations under the License.
15bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include "trunks/resource_manager.h"
184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include <algorithm>
204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include <map>
214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include <set>
224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include <string>
234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include <vector>
244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include <base/callback.h>
264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn#include "trunks/error_codes.h"
284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnnamespace {
304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnconst int kMaxCommandAttempts = 3;
324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnconst size_t kMinimumAuthorizationSize = 9;
334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnconst size_t kMessageHeaderSize = 10;
344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnconst trunks::TPM_HANDLE kMaxVirtualHandle =
354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    (trunks::HR_TRANSIENT + trunks::HR_HANDLE_MASK);
364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnclass ScopedBool {
384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn public:
394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  ScopedBool() : target_(nullptr) {}
404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  ~ScopedBool() {
414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (target_) {
424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      *target_ = false;
434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  void Enable(bool* target) {
464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    target_ = target;
474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    *target_ = true;
484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn private:
504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  bool* target_;
514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn};
524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}  // namespace
544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnnamespace trunks {
564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
574ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnResourceManager::ResourceManager(const TrunksFactory& factory,
584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                 CommandTransceiver* next_transceiver)
594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    : factory_(factory),
604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      next_transceiver_(next_transceiver) {}
614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
624ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnResourceManager::~ResourceManager() {}
634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::Initialize() {
654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = factory_.GetTpm()->StartupSync(TPM_SU_CLEAR, nullptr);
664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Ignore TPM_RC_INITIALIZE, that means it was already started.
679caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn  CHECK(result == TPM_RC_SUCCESS || result == TPM_RC_INITIALIZE)
689caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn      << "TPM startup failure: " << GetErrorString(result);
694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  result = factory_.GetTpm()->SelfTestSync(YES /* Full test. */, nullptr);
709caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn  CHECK_EQ(result, TPM_RC_SUCCESS) << "TPM self-test failure: "
719caf492818a4cc51ba471534d3fcaa84c9ce0278Darren Krahn                                   << GetErrorString(result);
724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Full control of the TPM is assumed and required. Existing transient object
734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // and session handles are mercilessly flushed.
744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (UINT32 handle_type : {HR_TRANSIENT,
754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                             HR_HMAC_SESSION,
764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                             HR_POLICY_SESSION}) {
774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPMI_YES_NO more_data = YES;
784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPMS_CAPABILITY_DATA data;
794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    UINT32 handle_range = handle_type;
804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    while (more_data) {
814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_HANDLES,
824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                    handle_range,
834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                    MAX_CAP_HANDLES,
844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                    &more_data,
854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                    &data,
864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                    nullptr);
874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        LOG(WARNING) << "Failed to query existing handles: "
894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                     << GetErrorString(result);
904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        break;
914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      const TPML_HANDLE& handle_list = data.data.handles;
934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      for (UINT32 i = 0; i < handle_list.count; ++i) {
944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        factory_.GetTpm()->FlushContextSync(handle_list.handle[i], nullptr);
954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (more_data) {
974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        // Adjust the range to be greater than the most recent handle so on the
984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        // next query we'll start where we left off.
994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        handle_range = handle_list.handle[handle_list.count-1];
1004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
1014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
1044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
1054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::SendCommand(
1064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::string& command,
1074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const ResponseCallback& callback) {
1084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  callback.Run(SendCommandAndWait(command));
1094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
1104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
1114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnstd::string ResourceManager::SendCommandAndWait(const std::string& command) {
1124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Sanitize the |command|. If this succeeds consistency of the command header
1134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // and the size of all other sections can be assumed.
1144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  MessageInfo command_info;
1154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = ParseCommand(command, &command_info);
1164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
1174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return CreateErrorResponse(result);
1184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // A special case for FlushContext. It requires special handling because it
1204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // has a handle as a parameter and because we need to cleanup if it succeeds.
1214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (command_info.code == TPM_CC_FlushContext) {
1224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return ProcessFlushContext(command, command_info);
1234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Process all the input handles, e.g. map virtual handles.
1254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::vector<TPM_HANDLE> updated_handles;
1264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (auto handle : command_info.handles) {
1274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_HANDLE tpm_handle;
1284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = ProcessInputHandle(command_info, handle, &tpm_handle);
1294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
1304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return CreateErrorResponse(result);
1314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    updated_handles.push_back(tpm_handle);
1334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string updated_command = ReplaceHandles(command, updated_handles);
1354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Make sure all the required sessions are loaded.
1364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (auto handle : command_info.session_handles) {
1374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = EnsureSessionIsLoaded(command_info, handle);
1384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
1394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return CreateErrorResponse(result);
1404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // On a ContextLoad we may need to map virtualized context data.
1434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (command_info.code == TPM_CC_ContextLoad) {
1444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    std::string actual_load_data = GetActualContextFromExternalContext(
1454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        command_info.parameter_data);
1464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Check equality to see if replacement is necessary, and check size to see
1474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // if the command looks like we expect (the idea is to avoid 'fixing'
1484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // malformed commands). Note: updated_command.size() is guaranteed to be >=
1494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // kMessageHeaderSize based on the sanitization in ParseCommand.
1504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (actual_load_data != command_info.parameter_data &&
1514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        actual_load_data.size() ==
1524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn            updated_command.size() - kMessageHeaderSize) {
1534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      // Replace the parameter section of the command with |actual_load_data|.
1544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      VLOG(1) << "REPLACE_EXTERNAL_CONTEXT";
1554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      updated_command.replace(kMessageHeaderSize, std::string::npos,
1564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                              actual_load_data);
1574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Send the |updated_command| to the next layer. Attempt to fix any actionable
1604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // warnings for up to kMaxCommandAttempts.
1614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string response;
1624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  MessageInfo response_info;
1634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  int attempts = 0;
1644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  while (attempts++ < kMaxCommandAttempts) {
1654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    response = next_transceiver_->SendCommandAndWait(updated_command);
1664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = ParseResponse(command_info, response, &response_info);
1674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
1684ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return CreateErrorResponse(result);
1694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!FixWarnings(command_info, response_info.code)) {
1714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      // No actionable warnings were handled.
1724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      break;
1734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
1754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (response_info.code == TPM_RC_SUCCESS) {
1764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (response_info.session_continued.size() !=
1774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        command_info.session_handles.size()) {
1784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      LOG(WARNING) << "Session count mismatch!";
1794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Cleanup any sessions that were not continued.
1814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    for (size_t i = 0; i < command_info.session_handles.size(); ++i) {
1824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (i < response_info.session_continued.size() &&
1834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn          !response_info.session_continued[i]) {
1844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        CleanupFlushedHandle(command_info.session_handles[i]);
1854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
1864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // On a successful context save we need to cache the context data in case it
1884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // needs to be virtualized later.
1894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (command_info.code == TPM_CC_ContextSave) {
1904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      ProcessExternalContextSave(command_info, response_info);
1914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Process all the output handles, which is loosely the inverse of the input
1934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // handle processing. E.g. virtualize handles.
1944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    std::vector<TPM_HANDLE> virtual_handles;
1954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    for (auto handle : response_info.handles) {
1964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      virtual_handles.push_back(ProcessOutputHandle(handle));
1974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
1984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    response = ReplaceHandles(response, virtual_handles);
1994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return response;
2014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
2024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
2034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnbool ResourceManager::ChooseSessionToEvict(
2044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::vector<TPM_HANDLE>& sessions_to_retain,
2054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_HANDLE* session_to_evict) {
2064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Build a list of candidates by excluding |sessions_to_retain|.
2074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::vector<TPM_HANDLE> candidates;
2084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (auto& item : session_handles_) {
2094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    HandleInfo& info = item.second;
2104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (info.is_loaded &&
2114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        std::find(sessions_to_retain.begin(),
2124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                  sessions_to_retain.end(),
2134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                  info.tpm_handle) == sessions_to_retain.end()) {
2144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      candidates.push_back(item.first);
2154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
2164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (candidates.empty()) {
2184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(WARNING) << "No sessions to evict.";
2194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return false;
2204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Choose the candidate with the earliest |time_of_last_use|.
2224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  auto oldest_iter = std::min_element(
2234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      candidates.begin(), candidates.end(),
2244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      [this](TPM_HANDLE a, TPM_HANDLE b) {
2254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return (session_handles_[a].time_of_last_use <
2264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                session_handles_[b].time_of_last_use);
2274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      });
2284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  *session_to_evict = *oldest_iter;
2294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return true;
2304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
2314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
2324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::CleanupFlushedHandle(TPM_HANDLE flushed_handle) {
2334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (IsObjectHandle(flushed_handle)) {
2344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // For transient object handles, remove both the actual and virtual handles.
2354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (virtual_object_handles_.count(flushed_handle) > 0) {
2364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      tpm_object_handles_.erase(
2374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn          virtual_object_handles_[flushed_handle].tpm_handle);
2384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      virtual_object_handles_.erase(flushed_handle);
2394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
2404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  } else if (IsSessionHandle(flushed_handle)) {
2414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    auto iter = session_handles_.find(flushed_handle);
2424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (iter == session_handles_.end()) {
2434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return;
2444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
2454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // For session handles, remove the handle and any associated context data.
2464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    HandleInfo& info = iter->second;
2474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!info.is_loaded) {
2484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      std::string actual_context_data;
2494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      Serialize_TPMS_CONTEXT(info.context, &actual_context_data);
2504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (actual_context_to_external_.count(actual_context_data) > 0) {
2514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        external_context_to_actual_.erase(
2524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn            actual_context_to_external_[actual_context_data]);
2534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        actual_context_to_external_.erase(actual_context_data);
2544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
2554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
2564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    session_handles_.erase(flushed_handle);
2574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    VLOG(1) << "CLEANUP_SESSION: " << std::hex << flushed_handle;
2584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
2604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
2614ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_HANDLE ResourceManager::CreateVirtualHandle() {
2624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_HANDLE handle;
2634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  do {
2644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    handle = next_virtual_handle_;
2654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (next_virtual_handle_ == kMaxVirtualHandle) {
2664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      next_virtual_handle_ = TRANSIENT_FIRST;
2674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    } else {
2684ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      ++next_virtual_handle_;
2694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
2704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  } while (virtual_object_handles_.count(handle) > 0);
2714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return handle;
2724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
2734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
2744ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::EnsureSessionIsLoaded(const MessageInfo& command_info,
2754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                              TPM_HANDLE session_handle) {
2764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // A password authorization can skip all this.
2774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (session_handle == TPM_RS_PW) {
2784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return TPM_RC_SUCCESS;
2794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  auto handle_iter = session_handles_.find(session_handle);
2814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (handle_iter == session_handles_.end()) {
2824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_HANDLE, FROM_HERE);
2834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  HandleInfo& handle_info = handle_iter->second;
2854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!handle_info.is_loaded) {
2864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_RC result = LoadContext(command_info, &handle_info);
2874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
2884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return result;
2894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
2904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    VLOG(1) << "RELOAD_SESSION: " << std::hex << session_handle;
2914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
2924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  handle_info.time_of_last_use = base::TimeTicks::Now();
2934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return TPM_RC_SUCCESS;
2944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
2954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
2964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::EvictObjects(const MessageInfo& command_info) {
2974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (auto& item : virtual_object_handles_) {
2984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    HandleInfo& info = item.second;
2994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!info.is_loaded ||
3004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        std::find(command_info.handles.begin(),
3014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                  command_info.handles.end(),
3024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                  item.first) != command_info.handles.end()) {
3034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      continue;
3044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_RC result = SaveContext(command_info, &info);
3064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
3074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      LOG(WARNING) << "Failed to save transient object: "
3084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                   << GetErrorString(result);
3094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      continue;
3104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = factory_.GetTpm()->FlushContextSync(info.tpm_handle, nullptr);
3124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
3134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      LOG(WARNING) << "Failed to evict transient object: "
3144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                   << GetErrorString(result);
3154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      continue;
3164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    tpm_object_handles_.erase(info.tpm_handle);
3184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    VLOG(1) << "EVICT_OBJECT: " << std::hex << info.tpm_handle;
3194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
3214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
3224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::EvictSession(const MessageInfo& command_info) {
3234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_HANDLE session_to_evict;
3244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!ChooseSessionToEvict(command_info.session_handles, &session_to_evict)) {
3254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return;
3264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  HandleInfo& info = session_handles_[session_to_evict];
3284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = SaveContext(command_info, &info);
3294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
3304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(WARNING) << "Failed to evict session: " << GetErrorString(result);
3314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(1) << "EVICT_SESSION: " << std::hex << session_to_evict;
3334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
3344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
3354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnstd::vector<TPM_HANDLE> ResourceManager::ExtractHandlesFromBuffer(
3364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    size_t number_of_handles,
3374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    std::string* buffer) {
3384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::vector<TPM_HANDLE> handles(number_of_handles);
3394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (size_t i = 0; i < number_of_handles; ++i) {
3404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_HANDLE handle;
3414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (TPM_RC_SUCCESS == Parse_TPM_HANDLE(buffer, &handle, nullptr)) {
3424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      handles[i] = handle;
3434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return handles;
3464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
3474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
3484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::FixContextGap(const MessageInfo& command_info) {
3494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::vector<TPM_HANDLE> sessions_to_ungap;
3504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (const auto& item : session_handles_) {
3514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const HandleInfo& info = item.second;
3524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!info.is_loaded) {
3534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      sessions_to_ungap.push_back(item.first);
3544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Sort by |time_of_create|.
3574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::sort(sessions_to_ungap.begin(), sessions_to_ungap.end(),
3584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn            [this](TPM_HANDLE a, TPM_HANDLE b) {
3594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn              return (session_handles_[a].time_of_create <
3604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                      session_handles_[b].time_of_create);
3614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn            });
3624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (auto handle : sessions_to_ungap) {
3634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    HandleInfo& info = session_handles_[handle];
3644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Loading and re-saving allows the TPM to assign a new context counter.
3654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    std::string old_context_blob;
3664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    Serialize_TPMS_CONTEXT(info.context, &old_context_blob);
3674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_RC result = LoadContext(command_info, &info);
3684ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
3694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      LOG(WARNING) << "Failed to un-gap session (load): "
3704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                   << GetErrorString(result);
3714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      continue;
3724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = SaveContext(command_info, &info);
3744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
3754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      LOG(WARNING) << "Failed to un-gap session (save): "
3764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                   << GetErrorString(result);
3774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      continue;
3784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // If this context is one that we're tracking for external use, update it.
3804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    auto iter = actual_context_to_external_.find(old_context_blob);
3814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (iter == actual_context_to_external_.end()) {
3824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      continue;
3834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
3844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    std::string new_context_blob;
3854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    Serialize_TPMS_CONTEXT(info.context, &new_context_blob);
3864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::string& external_context_blob = iter->second;
3874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    actual_context_to_external_[new_context_blob] = external_context_blob;
3884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    external_context_to_actual_[external_context_blob] = new_context_blob;
3894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    actual_context_to_external_.erase(old_context_blob);
3904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
3924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
3934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnbool ResourceManager::FixWarnings(const MessageInfo& command_info,
3944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                  TPM_RC result) {
3954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if ((result & RC_WARN) == 0) {
3964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return false;
3974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
3984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // This method can be called anytime without tracking whether the current
3994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // operation is already an attempt to fix a warning. All re-entrance issues
4004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // are dealt with here using the following rule: Never attempt to fix the same
4014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // warning twice.
4024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  ScopedBool scoped_bool;
4034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!fixing_warnings_) {
4044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    scoped_bool.Enable(&fixing_warnings_);
4054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    warnings_already_seen_.clear();
4064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  } else if (warnings_already_seen_.count(result) > 0) {
4074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return false;
4084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  warnings_already_seen_.insert(result);
4104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  switch (result) {
4114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    case TPM_RC_CONTEXT_GAP:
4124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      FixContextGap(command_info);
4134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return true;
4144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    case TPM_RC_OBJECT_MEMORY:
4154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    case TPM_RC_OBJECT_HANDLES:
4164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      EvictObjects(command_info);
4174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return true;
4184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    case TPM_RC_SESSION_MEMORY:
4194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      EvictSession(command_info);
4204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return true;
4214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    case TPM_RC_MEMORY:
4224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      EvictObjects(command_info);
4234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      EvictSession(command_info);
4244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return true;
4254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    case TPM_RC_SESSION_HANDLES:
4264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      FlushSession(command_info);
4274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return true;
4284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return false;
4304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::FlushSession(const MessageInfo& command_info) {
4334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_HANDLE session_to_flush;
4344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  LOG(WARNING) << "Resource manager needs to flush a session.";
4354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!ChooseSessionToEvict(command_info.session_handles, &session_to_flush)) {
4364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return;
4374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = factory_.GetTpm()->FlushContextSync(session_to_flush,
4394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                      nullptr);
4404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
4414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(WARNING) << "Failed to flush session: " << GetErrorString(result);
4424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return;
4434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CleanupFlushedHandle(session_to_flush);
4454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnstd::string ResourceManager::GetActualContextFromExternalContext(
4484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::string& external_context) {
4494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  auto iter = external_context_to_actual_.find(external_context);
4504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (iter == external_context_to_actual_.end()) {
4514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return external_context;
4524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return iter->second;
4544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnbool ResourceManager::IsObjectHandle(TPM_HANDLE handle) const {
4574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return ((handle & HR_RANGE_MASK) == HR_TRANSIENT);
4584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnbool ResourceManager::IsSessionHandle(TPM_HANDLE handle) const {
4614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return ((handle & HR_RANGE_MASK) == HR_HMAC_SESSION ||
4624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn          (handle & HR_RANGE_MASK) == HR_POLICY_SESSION);
4634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4654ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::LoadContext(const MessageInfo& command_info,
4664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                    HandleInfo* handle_info) {
4674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CHECK(!handle_info->is_loaded);
4684ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
4694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  int attempts = 0;
4704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  while (attempts++ < kMaxCommandAttempts) {
4714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = factory_.GetTpm()->ContextLoadSync(handle_info->context,
4724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                &handle_info->tpm_handle,
4734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                nullptr);
4744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!FixWarnings(command_info, result)) {
4754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      break;
4764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
4774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
4794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(ERROR) << __func__ << ": Failed to load context: "
4804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn               << GetErrorString(result);
4814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return result;
4824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
4834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  handle_info->is_loaded = true;
4844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return result;
4854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4874ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::MakeError(TPM_RC tpm_error,
4884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                  const ::tracked_objects::Location& location) {
4894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  LOG(ERROR) << "ResourceManager::" << location.function_name() << ":"
4904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn             << location.line_number() << ": " << GetErrorString(tpm_error);
4914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return tpm_error + kResourceManagerTpmErrorBase;
4924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
4934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
4944ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::ParseCommand(const std::string& command,
4954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                     MessageInfo* command_info) {
4964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CHECK(command_info);
4974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string buffer = command;
4984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_ST tag;
4994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = Parse_TPM_ST(&buffer, &tag, nullptr);
5004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
5014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(result, FROM_HERE);
5024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (tag != TPM_ST_SESSIONS && tag != TPM_ST_NO_SESSIONS) {
5044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_TAG, FROM_HERE);
5054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  command_info->has_sessions = (tag == TPM_ST_SESSIONS);
5074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
5084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  UINT32 size = 0;
5094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  result = Parse_UINT32(&buffer, &size, nullptr);
5104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
5114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(result, FROM_HERE);
5124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (size != command.size()) {
5144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_SIZE, FROM_HERE);
5154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
5174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  result = Parse_TPM_CC(&buffer, &command_info->code, nullptr);
5184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
5194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(result, FROM_HERE);
5204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (command_info->code < TPM_CC_FIRST || command_info->code > TPM_CC_LAST) {
5224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_COMMAND_CODE, FROM_HERE);
5234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
5254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  size_t number_of_handles = GetNumberOfRequestHandles(command_info->code);
5264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  command_info->handles = ExtractHandlesFromBuffer(number_of_handles, &buffer);
5274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (number_of_handles != command_info->handles.size()) {
5284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_SIZE, FROM_HERE);
5294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (command_info->has_sessions) {
5314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Sessions exist, so we're expecting a valid authorization size value.
5324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    UINT32 authorization_size = 0;
5334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = Parse_UINT32(&buffer, &authorization_size, nullptr);
5344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
5354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return MakeError(result, FROM_HERE);
5364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
5374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (buffer.size() < authorization_size ||
5384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        authorization_size < kMinimumAuthorizationSize) {
5394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return MakeError(TPM_RC_SIZE, FROM_HERE);
5404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
5414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Move out the parameter bytes, leaving only the authorization section.
5424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    command_info->parameter_data = buffer.substr(authorization_size);
5434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    buffer.erase(authorization_size);
5444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Parse as many authorization sessions as there are in the section.
5454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    while (!buffer.empty()) {
5464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      TPM_HANDLE handle;
5474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_TPM_HANDLE(&buffer, &handle, nullptr);
5484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
5494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
5504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
5514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (handle != TPM_RS_PW && session_handles_.count(handle) == 0) {
5524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(TPM_RC_HANDLE, FROM_HERE);
5534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
5544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      TPM2B_NONCE nonce;
5554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_TPM2B_NONCE(&buffer, &nonce, nullptr);
5564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
5574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
5584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
5594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      BYTE attributes;
5604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_BYTE(&buffer, &attributes, nullptr);
5614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
5624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
5634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
5644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      TPM2B_DIGEST authorization;
5654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_TPM2B_DIGEST(&buffer, &authorization, nullptr);
5664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
5674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
5684ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
5694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      command_info->session_handles.push_back(handle);
5704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      command_info->session_continued.push_back((attributes & 1) == 1);
5714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
5724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  } else {
5734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // No sessions, so all remaining data is parameter data.
5744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    command_info->parameter_data = buffer;
5754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return TPM_RC_SUCCESS;
5774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
5784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
5794ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::ParseResponse(const MessageInfo& command_info,
5804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                      const std::string& response,
5814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                      MessageInfo* response_info) {
5824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CHECK(response_info);
5834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string buffer = response;
5844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_ST tag;
5854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = Parse_TPM_ST(&buffer, &tag, nullptr);
5864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
5874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(result, FROM_HERE);
5884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (tag != TPM_ST_SESSIONS && tag != TPM_ST_NO_SESSIONS) {
5904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_TAG, FROM_HERE);
5914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  response_info->has_sessions = (tag == TPM_ST_SESSIONS);
5934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
5944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  UINT32 size = 0;
5954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  result = Parse_UINT32(&buffer, &size, nullptr);
5964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
5974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(result, FROM_HERE);
5984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
5994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (size != response.size()) {
6004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_SIZE, FROM_HERE);
6014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
6034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  result = Parse_TPM_RC(&buffer, &response_info->code, nullptr);
6044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
6054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(result, FROM_HERE);
6064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
6084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  size_t number_of_handles = GetNumberOfResponseHandles(command_info.code);
6094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  response_info->handles = ExtractHandlesFromBuffer(number_of_handles, &buffer);
6104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (number_of_handles != response_info->handles.size()) {
6114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_SIZE, FROM_HERE);
6124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (response_info->has_sessions) {
6144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Sessions exist, so we're expecting a valid parameter size value.
6154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    UINT32 parameter_size = 0;
6164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = Parse_UINT32(&buffer, &parameter_size, nullptr);
6174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
6184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return MakeError(result, FROM_HERE);
6194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
6204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (buffer.size() < parameter_size) {
6214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return MakeError(TPM_RC_SIZE, FROM_HERE);
6224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
6234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Move out the parameter bytes, leaving only the authorization section.
6244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    response_info->parameter_data = buffer.substr(0, parameter_size);
6254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    buffer.erase(0, parameter_size);
6264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Parse as many authorization sessions as there are in the section.
6274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    while (!buffer.empty()) {
6284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      TPM2B_NONCE nonce;
6294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_TPM2B_NONCE(&buffer, &nonce, nullptr);
6304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
6314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
6324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
6334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      BYTE attributes;
6344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_BYTE(&buffer, &attributes, nullptr);
6354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
6364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
6374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
6384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      TPM2B_DIGEST acknowledgement;
6394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      result = Parse_TPM2B_DIGEST(&buffer, &acknowledgement, nullptr);
6404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      if (result != TPM_RC_SUCCESS) {
6414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn        return MakeError(result, FROM_HERE);
6424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      }
6434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      response_info->session_continued.push_back((attributes & 1) == 1);
6444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
6454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  } else {
6464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // No sessions, so all remaining data is parameter data.
6474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    response_info->parameter_data = buffer;
6484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return TPM_RC_SUCCESS;
6504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
6514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
6524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::ProcessExternalContextSave(
6534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const MessageInfo& command_info,
6544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const MessageInfo& response_info) {
6554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CHECK_EQ(command_info.code, TPM_CC_ContextSave);
6564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (command_info.handles.size() != 1) {
6574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(WARNING) << "Invalid context save command.";
6584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return;
6594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // We know command_info.handles[0] is valid because this is validated when the
6614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // command is parsed.
6624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_HANDLE saved_handle = command_info.handles[0];
6634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Only track external context data for session handles.
6644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!IsSessionHandle(saved_handle)) {
6654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return;
6664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string mutable_parameter = response_info.parameter_data;
6684ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPMS_CONTEXT context;
6694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string context_blob;
6704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = Parse_TPMS_CONTEXT(&mutable_parameter,
6714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                     &context,
6724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                     &context_blob);
6734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
6744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(WARNING) << "Invalid context save response: " << GetErrorString(result);
6754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return;
6764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  auto iter = session_handles_.find(saved_handle);
6784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (iter != session_handles_.end()) {
6794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    iter->second.is_loaded = false;
6804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    iter->second.context = context;
6814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  } else {
6824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    // Unknown handle? Not anymore.
6834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(WARNING) << "Context for unknown handle.";
6844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    HandleInfo new_handle_info;
6854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    new_handle_info.Init(saved_handle);
6864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    new_handle_info.is_loaded = false;
6874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    new_handle_info.context = context;
6884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    session_handles_[saved_handle] = new_handle_info;
6894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
6904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Use the original context data as the 'external' context data. If this gets
6914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // virtualized, only the 'actual' context data will change.
6924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  external_context_to_actual_[context_blob] = context_blob;
6934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  actual_context_to_external_[context_blob] = context_blob;
6944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
6954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
6964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnstd::string ResourceManager::ProcessFlushContext(
6974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::string& command,
6984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const MessageInfo& command_info) {
6994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string buffer = command_info.parameter_data;
7004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // There must be exactly one handle in the parameters section.
7014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::vector<TPM_HANDLE> handles = ExtractHandlesFromBuffer(1, &buffer);
7024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (handles.size() != 1) {
7034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return CreateErrorResponse(MakeError(TPM_RC_SIZE, FROM_HERE));
7044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_HANDLE handle = handles[0];
7064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_HANDLE actual_handle = handle;
7074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (IsObjectHandle(handle)) {
7084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    auto iter = virtual_object_handles_.find(handle);
7094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (iter == virtual_object_handles_.end()) {
7104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return CreateErrorResponse(MakeError(TPM_RC_HANDLE, FROM_HERE));
7114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
7124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!iter->second.is_loaded) {
7134ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      // The handle wasn't loaded so no need to bother the TPM.
7144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      CleanupFlushedHandle(handle);
7154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return CreateErrorResponse(TPM_RC_SUCCESS);
7164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
7174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    actual_handle = iter->second.tpm_handle;
7184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Send a command with the original header but with |actual_handle| as the
7204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // parameter.
7214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string handle_blob;
7224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  Serialize_TPM_HANDLE(actual_handle, &handle_blob);
7234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string updated_command = command.substr(0, kMessageHeaderSize) +
7244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                handle_blob;
7254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // No need to loop and fix warnings, there are no actionable warnings on when
7264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // flushing context.
7274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string response = next_transceiver_->SendCommandAndWait(updated_command);
7284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  MessageInfo response_info;
7294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = ParseResponse(command_info, response, &response_info);
7304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
7314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return CreateErrorResponse(result);
7324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Cleanup the handle locally even if the TPM did not recognize it.
7344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (response_info.code == TPM_RC_SUCCESS ||
7354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      response_info.code == TPM_RC_HANDLE) {
7364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    CleanupFlushedHandle(handle);
7374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return response;
7394ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
7404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
7414ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::ProcessInputHandle(const MessageInfo& command_info,
7424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                           TPM_HANDLE virtual_handle,
7434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                           TPM_HANDLE* actual_handle) {
7444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Only transient object handles are virtualized.
7454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!IsObjectHandle(virtual_handle)) {
7464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    *actual_handle = virtual_handle;
7474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return TPM_RC_SUCCESS;
7484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  auto handle_iter = virtual_object_handles_.find(virtual_handle);
7504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (handle_iter == virtual_object_handles_.end()) {
7514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return MakeError(TPM_RC_HANDLE, FROM_HERE);
7524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7534ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  HandleInfo& handle_info = handle_iter->second;
7544ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!handle_info.is_loaded) {
7554ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_RC result = LoadContext(command_info, &handle_info);
7564ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (result != TPM_RC_SUCCESS) {
7574ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      return result;
7584ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
7594ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    tpm_object_handles_[handle_info.tpm_handle] = virtual_handle;
7604ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    VLOG(1) << "RELOAD_OBJECT: " << std::hex << virtual_handle;
7614ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7624ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(1) << "INPUT_HANDLE_REPLACE: " << std::hex << virtual_handle << " -> "
7634ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn          << std::hex << handle_info.tpm_handle;
7644ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  *actual_handle = handle_info.tpm_handle;
7654ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return TPM_RC_SUCCESS;
7664ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
7674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
7684ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_HANDLE ResourceManager::ProcessOutputHandle(TPM_HANDLE handle) {
7694ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Track, but do not virtualize, session handles.
7704ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (IsSessionHandle(handle)) {
7714ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    auto session_handle_iter = session_handles_.find(handle);
7724ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (session_handle_iter == session_handles_.end()) {
7734ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      HandleInfo new_handle_info;
7744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      new_handle_info.Init(handle);
7754ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      session_handles_[handle] = new_handle_info;
7764ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      VLOG(1) << "OUTPUT_HANDLE_NEW_SESSION: " << std::hex << handle;
7774ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
7784ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return handle;
7794ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7804ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  // Only transient object handles are virtualized.
7814ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (!IsObjectHandle(handle)) {
7824ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return handle;
7834ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  auto virtual_handle_iter = tpm_object_handles_.find(handle);
7854ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (virtual_handle_iter == tpm_object_handles_.end()) {
7864ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    TPM_HANDLE new_virtual_handle = CreateVirtualHandle();
7874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    HandleInfo new_handle_info;
7884ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    new_handle_info.Init(handle);
7894ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    virtual_object_handles_[new_virtual_handle] = new_handle_info;
7904ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    tpm_object_handles_[handle] = new_virtual_handle;
7914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    VLOG(1) << "OUTPUT_HANDLE_NEW_VIRTUAL: " << std::hex << handle << " -> "
7924ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn            << std::hex << new_virtual_handle;
7934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return new_virtual_handle;
7944ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
7954ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(1) << "OUTPUT_HANDLE_REPLACE: " << std::hex << handle << " -> "
7964ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn          << std::hex << virtual_handle_iter->second;
7974ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return virtual_handle_iter->second;
7984ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
7994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
8004ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnstd::string ResourceManager::ReplaceHandles(
8014ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::string& message,
8024ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    const std::vector<TPM_HANDLE>& new_handles) {
8034ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string handles_blob;
8044ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  for (auto handle : new_handles) {
8054ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    CHECK_EQ(Serialize_TPM_HANDLE(handle, &handles_blob), TPM_RC_SUCCESS);
8064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
8074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  std::string mutable_message = message;
8084ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CHECK_GE(message.size(), kMessageHeaderSize + handles_blob.size());
8094ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return mutable_message.replace(kMessageHeaderSize, handles_blob.size(),
8104ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                 handles_blob);
8114ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
8124ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
8134ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnTPM_RC ResourceManager::SaveContext(const MessageInfo& command_info,
8144ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                    HandleInfo* handle_info) {
8154ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  CHECK(handle_info->is_loaded);
8164ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
8174ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  int attempts = 0;
8184ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  while (attempts++ < kMaxCommandAttempts) {
8194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    std::string tpm_handle_name;
8204ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    Serialize_TPM_HANDLE(handle_info->tpm_handle, &tpm_handle_name);
8214ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    result = factory_.GetTpm()->ContextSaveSync(handle_info->tpm_handle,
8224ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                tpm_handle_name,
8234ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                &handle_info->context,
8244ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn                                                nullptr);
8254ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    if (!FixWarnings(command_info, result)) {
8264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      break;
8274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    }
8284ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
8294ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  if (result != TPM_RC_SUCCESS) {
8304ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    LOG(ERROR) << __func__ << ": Failed to load context: "
8314ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn               << GetErrorString(result);
8324ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    return result;
8334ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  }
8344ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  handle_info->is_loaded = false;
8354ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  return result;
8364ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
8374ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
8384ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
8394ede7fcc1571b23867536b2506900fc3987c2dd5Darren KrahnResourceManager::HandleInfo::HandleInfo()
8404ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    : is_loaded(false),
8414ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn      tpm_handle(0) {
8424ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  memset(&context, 0, sizeof(TPMS_CONTEXT));
8434ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
8444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
8454ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahnvoid ResourceManager::HandleInfo::Init(TPM_HANDLE handle) {
8464ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  tpm_handle = handle;
8474ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  is_loaded = true;
8484ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  time_of_create = base::TimeTicks::Now();
8494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  time_of_last_use = base::TimeTicks::Now();
8504ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}
8514ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn
8524ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn}  // namespace trunks
853