1 /* 2 * Copyright (C) 2015 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 #define LOG_TAG "KeystoreOperation" 17 18 #include "operation.h" 19 20 #include <algorithm> 21 22 namespace keystore { 23 24 OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient) 25 : mDeathRecipient(deathRecipient) {} 26 27 sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, 28 const sp<Keymaster>& dev, const sp<IBinder>& appToken, 29 KeyCharacteristics&& characteristics, 30 const hidl_vec<KeyParameter>& params, bool pruneable) { 31 sp<IBinder> token = new ::android::BBinder(); 32 mMap.emplace(token, Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken, 33 params)); 34 if (pruneable) mLru.push_back(token); 35 if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient); 36 mAppTokenMap[appToken].push_back(token); 37 return token; 38 } 39 40 NullOr<const Operation&> OperationMap::getOperation(const sp<IBinder>& token) { 41 auto entry = mMap.find(token); 42 if (entry == mMap.end()) return {}; 43 44 updateLru(token); 45 return entry->second; 46 } 47 48 void OperationMap::updateLru(const sp<IBinder>& token) { 49 auto lruEntry = std::find(mLru.begin(), mLru.end(), token); 50 if (lruEntry != mLru.end()) { 51 mLru.erase(lruEntry); 52 mLru.push_back(token); 53 } 54 } 55 56 NullOr<Operation> OperationMap::removeOperation(const sp<IBinder>& token, bool wasSuccessful) { 57 auto entry = mMap.find(token); 58 if (entry == mMap.end()) return {}; 59 60 Operation op = std::move(entry->second); 61 uploadOpAsProto(op, wasSuccessful); 62 mMap.erase(entry); 63 64 auto lruEntry = std::find(mLru.begin(), mLru.end(), token); 65 if (lruEntry != mLru.end()) mLru.erase(lruEntry); 66 removeOperationTracking(token, op.appToken); 67 return op; 68 } 69 70 void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) { 71 auto appEntry = mAppTokenMap.find(appToken); 72 if (appEntry == mAppTokenMap.end()) { 73 ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get()); 74 return; 75 } 76 auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token); 77 appEntry->second.erase(tokenEntry); 78 // Stop listening for death if all operations tied to the token have finished. 79 if (appEntry->second.size() == 0) { 80 appToken->unlinkToDeath(mDeathRecipient); 81 mAppTokenMap.erase(appEntry); 82 } 83 } 84 85 bool OperationMap::hasPruneableOperation() const { 86 return !mLru.empty(); 87 } 88 89 size_t OperationMap::getPruneableOperationCount() const { 90 return mLru.size(); 91 } 92 93 sp<IBinder> OperationMap::getOldestPruneableOperation() { 94 if (!hasPruneableOperation()) return sp<IBinder>(nullptr); 95 return mLru.front(); 96 } 97 98 void OperationMap::setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken) { 99 auto entry = mMap.find(token); 100 if (entry == mMap.end()) return; 101 102 entry->second.authToken = std::move(authToken); 103 } 104 105 void OperationMap::setOperationVerificationToken(const sp<IBinder>& token, 106 VerificationToken verificationToken) { 107 auto entry = mMap.find(token); 108 if (entry == mMap.end()) return; 109 110 entry->second.verificationToken = std::move(verificationToken); 111 } 112 113 std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) { 114 auto appEntry = mAppTokenMap.find(appToken); 115 if (appEntry == mAppTokenMap.end()) return {}; 116 return appEntry->second; 117 } 118 119 } // namespace keystore 120