blob: e871f83e113afc05caed0441377adf0ff3e831b7 [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
22namespace android {
23OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
24 : mDeathRecipient(deathRecipient) {
25}
26
27sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle,
28 const keymaster1_device_t* dev,
Chad Brubaker06801e02015-03-31 15:13:13 -070029 sp<IBinder> appToken,
Chad Brubakerad6514a2015-04-09 14:00:26 -070030 keymaster_key_characteristics_t* characteristics,
31 bool pruneable) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080032 sp<IBinder> token = new BBinder();
Chad Brubakerad6514a2015-04-09 14:00:26 -070033 mMap[token] = std::move(Operation(handle, dev, characteristics, appToken));
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080034 if (pruneable) {
35 mLru.push_back(token);
36 }
37 if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) {
38 appToken->linkToDeath(mDeathRecipient);
39 }
40 mAppTokenMap[appToken].push_back(token);
41 return token;
42}
43
44bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
Chad Brubaker06801e02015-03-31 15:13:13 -070045 const keymaster1_device_t** outDevice,
Chad Brubakerad6514a2015-04-09 14:00:26 -070046 const keymaster_key_characteristics_t** outCharacteristics) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080047 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 *outDevice = entry->second.device;
Chad Brubakerad6514a2015-04-09 14:00:26 -070058 if (outCharacteristics) {
59 *outCharacteristics = entry->second.characteristics.get();
Chad Brubaker06801e02015-03-31 15:13:13 -070060 }
Chad Brubaker40a1a9b2015-02-20 14:08:13 -080061 return true;
62}
63
64void OperationMap::updateLru(sp<IBinder> token) {
65 auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
66 if (lruEntry != mLru.end()) {
67 mLru.erase(lruEntry);
68 mLru.push_back(token);
69 }
70}
71
72bool OperationMap::removeOperation(sp<IBinder> token) {
73 auto entry = mMap.find(token);
74 if (entry == mMap.end()) {
75 return false;
76 }
77 sp<IBinder> appToken = entry->second.appToken;
78 mMap.erase(entry);
79 auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
80 if (lruEntry != mLru.end()) {
81 mLru.erase(lruEntry);
82 }
83 removeOperationTracking(token, appToken);
84 return true;
85}
86
87void OperationMap::removeOperationTracking(sp<IBinder> token, sp<IBinder> appToken) {
88 auto appEntry = mAppTokenMap.find(appToken);
89 if (appEntry == mAppTokenMap.end()) {
90 ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get());
91 return;
92 }
93 auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token);
94 appEntry->second.erase(tokenEntry);
95 // Stop listening for death if all operations tied to the token have finished.
96 if (appEntry->second.size() == 0) {
97 appToken->unlinkToDeath(mDeathRecipient);
98 mAppTokenMap.erase(appEntry);
99 }
100}
101
102bool OperationMap::hasPruneableOperation() {
103 return mLru.size() != 0;
104}
105
106sp<IBinder> OperationMap::getOldestPruneableOperation() {
107 if (!hasPruneableOperation()) {
108 return sp<IBinder>(NULL);
109 }
110 return mLru[0];
111}
112
113std::vector<sp<IBinder>> OperationMap::getOperationsForToken(sp<IBinder> appToken) {
114 auto appEntry = mAppTokenMap.find(appToken);
115 if (appEntry != mAppTokenMap.end()) {
116 return appEntry->second;
117 } else {
118 return std::vector<sp<IBinder>>();
119 }
120}
121
122OperationMap::Operation::Operation(keymaster_operation_handle_t handle_,
123 const keymaster1_device_t* device_,
Chad Brubakerad6514a2015-04-09 14:00:26 -0700124 keymaster_key_characteristics_t* characteristics_,
Chad Brubaker40a1a9b2015-02-20 14:08:13 -0800125 sp<IBinder> appToken_)
126 : handle(handle_),
127 device(device_),
Chad Brubakerad6514a2015-04-09 14:00:26 -0700128 characteristics(characteristics_),
Chad Brubaker40a1a9b2015-02-20 14:08:13 -0800129 appToken(appToken_) {
130}
131
Chad Brubakerad6514a2015-04-09 14:00:26 -0700132OperationMap::Operation::Operation() : handle(0), device(NULL), characteristics(), appToken(NULL) {
Chad Brubaker40a1a9b2015-02-20 14:08:13 -0800133}
134} // namespace android