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 sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle, uint64_t keyid, 27 keymaster_purpose_t purpose, const keymaster2_device_t* dev, 28 sp<IBinder> appToken, 29 keymaster_key_characteristics_t* characteristics, 30 bool pruneable) { 31 sp<IBinder> token = new BBinder(); 32 mMap[token] = Operation(handle, keyid, purpose, dev, characteristics, appToken); 33 if (pruneable) { 34 mLru.push_back(token); 35 } 36 if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) { 37 appToken->linkToDeath(mDeathRecipient); 38 } 39 mAppTokenMap[appToken].push_back(token); 40 return token; 41 } 42 43 bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle, 44 uint64_t* outKeyid, keymaster_purpose_t* outPurpose, 45 const keymaster2_device_t** outDevice, 46 const keymaster_key_characteristics_t** 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.get(); 62 } 63 return true; 64 } 65 66 void OperationMap::updateLru(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 74 bool OperationMap::removeOperation(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 89 void OperationMap::removeOperationTracking(sp<IBinder> token, 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 104 bool OperationMap::hasPruneableOperation() const { 105 return mLru.size() != 0; 106 } 107 108 size_t OperationMap::getPruneableOperationCount() const { 109 return mLru.size(); 110 } 111 112 sp<IBinder> OperationMap::getOldestPruneableOperation() { 113 if (!hasPruneableOperation()) { 114 return sp<IBinder>(NULL); 115 } 116 return mLru[0]; 117 } 118 119 bool OperationMap::getOperationAuthToken(sp<IBinder> token, const hw_auth_token_t** outToken) { 120 auto entry = mMap.find(token); 121 if (entry == mMap.end()) { 122 return false; 123 } 124 *outToken = entry->second.authToken.get(); 125 return true; 126 } 127 128 bool OperationMap::setOperationAuthToken(sp<IBinder> token, const hw_auth_token_t* authToken) { 129 auto entry = mMap.find(token); 130 if (entry == mMap.end()) { 131 return false; 132 } 133 entry->second.authToken.reset(new hw_auth_token_t); 134 *entry->second.authToken = *authToken; 135 return true; 136 } 137 138 std::vector<sp<IBinder>> OperationMap::getOperationsForToken(sp<IBinder> appToken) { 139 auto appEntry = mAppTokenMap.find(appToken); 140 if (appEntry != mAppTokenMap.end()) { 141 return appEntry->second; 142 } else { 143 return std::vector<sp<IBinder>>(); 144 } 145 } 146 147 OperationMap::Operation::Operation(keymaster_operation_handle_t handle_, uint64_t keyid_, 148 keymaster_purpose_t purpose_, const keymaster2_device_t* device_, 149 keymaster_key_characteristics_t* characteristics_, 150 sp<IBinder> appToken_) 151 : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_), 152 characteristics(characteristics_), appToken(appToken_) {} 153 154 OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) {} 155 156 } // namespace android 157