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 22namespace keystore { 23using namespace android; 24 25OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient) 26 : mDeathRecipient(deathRecipient) {} 27 28sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose, 29 const OperationMap::km_device_t& dev, 30 const sp<IBinder>& appToken, 31 KeyCharacteristics&& characteristics, bool pruneable) { 32 sp<IBinder> token = new BBinder(); 33 mMap[token] = Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken); 34 if (pruneable) { 35 mLru.push_back(token); 36 } 37 if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) { 38 appToken->linkToDeath(mDeathRecipient); 39 } 40 mAppTokenMap[appToken].push_back(token); 41 return token; 42} 43 44bool OperationMap::getOperation(const sp<IBinder>& token, uint64_t* outHandle, uint64_t* outKeyid, 45 KeyPurpose* outPurpose, km_device_t* outDevice, 46 const KeyCharacteristics** outCharacteristics) { 47 if (!outHandle || !outDevice) { 48 return false; 49 } 50 auto entry = mMap.find(token); 51 if (entry == mMap.end()) { 52 return false; 53 } 54 updateLru(token); 55 56 *outHandle = entry->second.handle; 57 *outKeyid = entry->second.keyid; 58 *outPurpose = entry->second.purpose; 59 *outDevice = entry->second.device; 60 if (outCharacteristics) { 61 *outCharacteristics = &entry->second.characteristics; 62 } 63 return true; 64} 65 66void OperationMap::updateLru(const sp<IBinder>& token) { 67 auto lruEntry = std::find(mLru.begin(), mLru.end(), token); 68 if (lruEntry != mLru.end()) { 69 mLru.erase(lruEntry); 70 mLru.push_back(token); 71 } 72} 73 74bool OperationMap::removeOperation(const sp<IBinder>& token) { 75 auto entry = mMap.find(token); 76 if (entry == mMap.end()) { 77 return false; 78 } 79 sp<IBinder> appToken = entry->second.appToken; 80 mMap.erase(entry); 81 auto lruEntry = std::find(mLru.begin(), mLru.end(), token); 82 if (lruEntry != mLru.end()) { 83 mLru.erase(lruEntry); 84 } 85 removeOperationTracking(token, appToken); 86 return true; 87} 88 89void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) { 90 auto appEntry = mAppTokenMap.find(appToken); 91 if (appEntry == mAppTokenMap.end()) { 92 ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get()); 93 return; 94 } 95 auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token); 96 appEntry->second.erase(tokenEntry); 97 // Stop listening for death if all operations tied to the token have finished. 98 if (appEntry->second.size() == 0) { 99 appToken->unlinkToDeath(mDeathRecipient); 100 mAppTokenMap.erase(appEntry); 101 } 102} 103 104bool OperationMap::hasPruneableOperation() const { 105 return mLru.size() != 0; 106} 107 108size_t OperationMap::getPruneableOperationCount() const { 109 return mLru.size(); 110} 111 112sp<IBinder> OperationMap::getOldestPruneableOperation() { 113 if (!hasPruneableOperation()) { 114 return sp<IBinder>(NULL); 115 } 116 return mLru[0]; 117} 118 119bool OperationMap::getOperationAuthToken(const sp<IBinder>& token, 120 const HardwareAuthToken** outToken) { 121 auto entry = mMap.find(token); 122 if (entry == mMap.end()) { 123 return false; 124 } 125 *outToken = entry->second.authToken.get(); 126 return true; 127} 128 129bool OperationMap::setOperationAuthToken(const sp<IBinder>& token, 130 const HardwareAuthToken* authToken) { 131 auto entry = mMap.find(token); 132 if (entry == mMap.end()) { 133 return false; 134 } 135 entry->second.authToken.reset(new HardwareAuthToken); 136 *entry->second.authToken = *authToken; 137 return true; 138} 139 140std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) { 141 auto appEntry = mAppTokenMap.find(appToken); 142 if (appEntry != mAppTokenMap.end()) { 143 return appEntry->second; 144 } else { 145 return std::vector<sp<IBinder>>(); 146 } 147} 148 149OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_, 150 const OperationMap::km_device_t& device_, 151 KeyCharacteristics&& characteristics_, sp<IBinder> appToken_) 152 : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_), 153 characteristics(characteristics_), appToken(appToken_) {} 154 155OperationMap::Operation::Operation() 156 : handle(0), keyid(0), device(nullptr), characteristics(), appToken(nullptr) {} 157 158} // namespace android 159