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