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