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, ¶meter_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