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