operation.cpp revision 9221bff2f13451ef330135bb32ea96de2a8b09cc
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 android { 23OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient) 24 : mDeathRecipient(deathRecipient) { 25} 26 27sp<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 45bool 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 68void 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 76bool 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 91void 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 106bool OperationMap::hasPruneableOperation() { 107 return mLru.size() != 0; 108} 109 110sp<IBinder> OperationMap::getOldestPruneableOperation() { 111 if (!hasPruneableOperation()) { 112 return sp<IBinder>(NULL); 113 } 114 return mLru[0]; 115} 116 117bool OperationMap::getOperationAuthToken(sp<IBinder> token, const hw_auth_token_t** outToken) { 118 auto entry = mMap.find(token); 119 if (entry == mMap.end()) { 120 return false; 121 } 122 *outToken = entry->second.authToken.get(); 123 return true; 124} 125 126bool OperationMap::setOperationAuthToken(sp<IBinder> token, const hw_auth_token_t* authToken) { 127 auto entry = mMap.find(token); 128 if (entry == mMap.end()) { 129 return false; 130 } 131 entry->second.authToken.reset(new hw_auth_token_t); 132 *entry->second.authToken = *authToken; 133 return true; 134} 135 136std::vector<sp<IBinder>> OperationMap::getOperationsForToken(sp<IBinder> appToken) { 137 auto appEntry = mAppTokenMap.find(appToken); 138 if (appEntry != mAppTokenMap.end()) { 139 return appEntry->second; 140 } else { 141 return std::vector<sp<IBinder>>(); 142 } 143} 144 145OperationMap::Operation::Operation(keymaster_operation_handle_t handle_, 146 uint64_t keyid_, 147 keymaster_purpose_t purpose_, 148 const keymaster1_device_t* device_, 149 keymaster_key_characteristics_t* characteristics_, 150 sp<IBinder> appToken_) 151 : handle(handle_), 152 keyid(keyid_), 153 purpose(purpose_), 154 device(device_), 155 characteristics(characteristics_), 156 appToken(appToken_) { 157} 158 159OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) { 160} 161} // namespace android 162