blob: 66fcee28f111be272f92164865404c51b04c33bc [file] [log] [blame]
Chad Brubaker40a1a9b2015-02-20 14:08:13 -08001/*
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
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010022namespace keystore {
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010023
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080024OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
Shawn Willden715d0232016-01-21 00:45:13 -070025 : mDeathRecipient(deathRecipient) {}
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080026
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010027sp<IBinder> OperationMap::addOperation(uint64_t handle, uint64_t keyid, KeyPurpose purpose,
28 const OperationMap::km_device_t& dev,
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -070029 const sp<IBinder>& appToken,
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +010030 KeyCharacteristics&& characteristics, bool pruneable) {
Shawn Willdenda6dcc32017-12-03 14:56:05 -070031 sp<IBinder> token = new ::android::BBinder();
32 mMap.emplace(token,
33 Operation(handle, keyid, purpose, dev, std::move(characteristics), appToken));
34 if (pruneable) mLru.push_back(token);
35 if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) appToken->linkToDeath(mDeathRecipient);
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080036 mAppTokenMap[appToken].push_back(token);
Shawn Willdenda6dcc32017-12-03 14:56:05 -070037
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080038 return token;
39}
40
Shawn Willdenda6dcc32017-12-03 14:56:05 -070041NullOr<const OperationMap::Operation&> OperationMap::getOperation(const sp<IBinder>& token) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080042 auto entry = mMap.find(token);
Shawn Willdenda6dcc32017-12-03 14:56:05 -070043 if (entry == mMap.end()) return {};
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080044
Shawn Willdenda6dcc32017-12-03 14:56:05 -070045 updateLru(token);
46 return entry->second;
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080047}
48
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -070049void OperationMap::updateLru(const sp<IBinder>& token) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080050 auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
51 if (lruEntry != mLru.end()) {
52 mLru.erase(lruEntry);
53 mLru.push_back(token);
54 }
55}
56
Shawn Willdenda6dcc32017-12-03 14:56:05 -070057NullOr<OperationMap::Operation> OperationMap::removeOperation(const sp<IBinder>& token) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080058 auto entry = mMap.find(token);
Shawn Willdenda6dcc32017-12-03 14:56:05 -070059 if (entry == mMap.end()) return {};
60
61 Operation op = std::move(entry->second);
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080062 mMap.erase(entry);
Shawn Willdenda6dcc32017-12-03 14:56:05 -070063
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080064 auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
Shawn Willdenda6dcc32017-12-03 14:56:05 -070065 if (lruEntry != mLru.end()) mLru.erase(lruEntry);
66 removeOperationTracking(token, op.appToken);
67
68 return op;
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080069}
70
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -070071void OperationMap::removeOperationTracking(const sp<IBinder>& token, const sp<IBinder>& appToken) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080072 auto appEntry = mAppTokenMap.find(appToken);
73 if (appEntry == mAppTokenMap.end()) {
74 ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get());
75 return;
76 }
77 auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token);
78 appEntry->second.erase(tokenEntry);
79 // Stop listening for death if all operations tied to the token have finished.
80 if (appEntry->second.size() == 0) {
81 appToken->unlinkToDeath(mDeathRecipient);
82 mAppTokenMap.erase(appEntry);
83 }
84}
85
Alex Klyubin700c1a32015-06-23 15:21:51 -070086bool OperationMap::hasPruneableOperation() const {
Shawn Willdenda6dcc32017-12-03 14:56:05 -070087 return !mLru.empty();
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080088}
89
Alex Klyubin700c1a32015-06-23 15:21:51 -070090size_t OperationMap::getPruneableOperationCount() const {
91 return mLru.size();
92}
93
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080094sp<IBinder> OperationMap::getOldestPruneableOperation() {
Shawn Willdenda6dcc32017-12-03 14:56:05 -070095 if (!hasPruneableOperation()) return sp<IBinder>(nullptr);
96 return mLru.front();
Chad Brubaker0cf34a22015-04-23 11:06:16 -070097}
98
Shawn Willdendebb61e2017-12-03 12:51:19 -070099bool OperationMap::setOperationAuthToken(const sp<IBinder>& token, HardwareAuthToken authToken) {
Chad Brubaker0cf34a22015-04-23 11:06:16 -0700100 auto entry = mMap.find(token);
Shawn Willdenda6dcc32017-12-03 14:56:05 -0700101 if (entry == mMap.end()) return false;
102
Shawn Willdendebb61e2017-12-03 12:51:19 -0700103 entry->second.authToken = std::make_unique<HardwareAuthToken>(std::move(authToken));
Chad Brubaker0cf34a22015-04-23 11:06:16 -0700104 return true;
105}
106
Chih-Hung Hsieh24b2a392016-07-28 10:35:24 -0700107std::vector<sp<IBinder>> OperationMap::getOperationsForToken(const sp<IBinder>& appToken) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -0800108 auto appEntry = mAppTokenMap.find(appToken);
Shawn Willdenda6dcc32017-12-03 14:56:05 -0700109 if (appEntry == mAppTokenMap.end()) return {};
110 return appEntry->second;
Chad Brubaker40a1a9b2015-02-20 14:08:13 -0800111}
112
Janis Danisevskisc7a9fa22016-10-13 18:43:45 +0100113OperationMap::Operation::Operation(uint64_t handle_, uint64_t keyid_, KeyPurpose purpose_,
114 const OperationMap::km_device_t& device_,
115 KeyCharacteristics&& characteristics_, sp<IBinder> appToken_)
Shawn Willden715d0232016-01-21 00:45:13 -0700116 : handle(handle_), keyid(keyid_), purpose(purpose_), device(device_),
117 characteristics(characteristics_), appToken(appToken_) {}
Chad Brubaker40a1a9b2015-02-20 14:08:13 -0800118
Shawn Willdenda6dcc32017-12-03 14:56:05 -0700119} // namespace keystore