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 #include <android-base/logging.h>
22 #include <mutex>
23 
24 namespace keystore {
25 
OperationMap(IBinder::DeathRecipient * deathRecipient)26 OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
27     : mDeathRecipient(deathRecipient) {}
28 
addOperation(uint64_t handle,uint64_t keyid,KeyPurpose purpose,const sp<Keymaster> & dev,const sp<IBinder> & appToken,KeyCharacteristics && characteristics,const hidl_vec<KeyParameter> & params,bool pruneable)29 sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
30                                        const sp<Keymaster>& dev, const sp<IBinder>& appToken,
31                                        KeyCharacteristics&& characteristics,
32                                        const hidl_vec<KeyParameter>& params, bool pruneable) {
33     sp<IBinder> token = new ::android::BBinder();
34     mMap.emplace(token, std::make_shared<Operation>(handle, keyid, purpose, dev,
35                                                     std::move(characteristics), appToken, params));
36     if (pruneable) mLru.push_back(token);
37     if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient);
38     mAppTokenMap[appToken].push_back(token);
39     return token;
40 }
41 
getOperation(const sp<IBinder> & token)42 std::shared_ptr<Operation> OperationMap::getOperation(const sp<IBinder>& token) {
43     auto entry = mMap.find(token);
44     if (entry == mMap.end()) return {};
45 
46     auto op = entry->second;
47 
48     updateLru(token);
49     return op;
50 }
51 
updateLru(const sp<IBinder> & token)52 void OperationMap::updateLru(const sp<IBinder>& token) {
53     auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
54     if (lruEntry != mLru.end()) {
55         mLru.erase(lruEntry);
56         mLru.push_back(token);
57     }
58 }
59 
removeOperation(const sp<IBinder> & token,bool wasSuccessful)60 std::shared_ptr<Operation> OperationMap::removeOperation(const sp<IBinder>& token,
61                                                          bool wasSuccessful) {
62     auto entry = mMap.find(token);
63     if (entry == mMap.end()) return {};
64 
65     auto op = entry->second;
66     operationUploader.uploadOpAsProto(*op, wasSuccessful);
67     mMap.erase(entry);
68 
69     auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
70     if (lruEntry != mLru.end()) mLru.erase(lruEntry);
71     removeOperationTracking(token, op->appToken);
72     return op;
73 }
74 
removeOperationTracking(const sp<IBinder> & token,const sp<IBinder> & appToken)75 void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) {
76     auto appEntry = mAppTokenMap.find(appToken);
77     if (appEntry == mAppTokenMap.end()) {
78         ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get());
79         return;
80     }
81     auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token);
82     appEntry->second.erase(tokenEntry);
83     // Stop listening for death if all operations tied to the token have finished.
84     if (appEntry->second.size() == 0) {
85         appToken->unlinkToDeath(mDeathRecipient);
86         mAppTokenMap.erase(appEntry);
87     }
88 }
89 
getOldestPruneableOperation()90 sp<IBinder> OperationMap::getOldestPruneableOperation() {
91     if (mLru.size() == 0) return {};
92 
93     return {mLru.front()};
94 }
95 
getOperationsForToken(const sp<IBinder> & appToken)96 std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) {
97     auto appEntry = mAppTokenMap.find(appToken);
98     if (appEntry == mAppTokenMap.end()) return {};
99     return appEntry->second;
100 }
101 
102 }  // namespace keystore
103