1 // 2 // Copyright (C) 2020 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #pragma once 17 18 #include <cstdint> 19 #include <memory> 20 #include <mutex> 21 #include <set> 22 23 #include <tss2/tss2_esys.h> 24 25 namespace cuttlefish { 26 27 class EsysLock { 28 public: 29 ESYS_CONTEXT* operator*() const { return esys_; } 30 31 private: 32 EsysLock(ESYS_CONTEXT*, std::unique_lock<std::mutex>); 33 34 ESYS_CONTEXT* esys_; 35 std::unique_lock<std::mutex> guard_; 36 37 friend class TpmResourceManager; 38 }; 39 40 /** 41 * Object slot manager for TPM memory. The TPM can only hold a fixed number of 42 * objects at once. Some TPM operations are defined to consume slots either 43 * temporarily or until the resource is explicitly unloaded. 44 * 45 * This implementation is intended for future extension, to track what objects 46 * are resident if we run out of space, or implement optimizations like LRU 47 * caching to avoid re-loading often-used resources. 48 */ 49 class TpmResourceManager { 50 public: 51 class ObjectSlot { 52 public: 53 friend class TpmResourceManager; 54 55 ~ObjectSlot(); 56 57 ESYS_TR get(); 58 void set(ESYS_TR resource); 59 private: 60 ObjectSlot(TpmResourceManager* resource_manager); 61 ObjectSlot(TpmResourceManager* resource_manager, ESYS_TR resource); 62 63 TpmResourceManager* resource_manager_; 64 ESYS_TR resource_; 65 }; 66 67 TpmResourceManager(ESYS_CONTEXT* esys); 68 ~TpmResourceManager(); 69 70 // Returns a wrapped ESYS_CONTEXT* that can be used with Esys calls that also 71 // holds a lock. Callers should not hold onto the inner ESYS_CONTEXT* past the 72 // lifetime of the lock. 73 EsysLock Esys(); 74 std::shared_ptr<ObjectSlot> ReserveSlot(); 75 76 private: 77 std::mutex mu_; 78 ESYS_CONTEXT* esys_; 79 const std::uint32_t maximum_object_slots_; 80 std::atomic<std::uint32_t> used_slots_; 81 }; 82 83 using TpmObjectSlot = std::shared_ptr<TpmResourceManager::ObjectSlot>; 84 85 } // namespace cuttlefish 86