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