Home | History | Annotate | Download | only in keystore
      1 /*
      2  * Copyright (C) 2014 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 
     17 #define LOG_TAG "keystore"
     18 
     19 #include "keymaster_enforcement.h"
     20 
     21 #include <assert.h>
     22 #include <inttypes.h>
     23 #include <limits.h>
     24 #include <string.h>
     25 
     26 #include <openssl/evp.h>
     27 
     28 #include <cutils/log.h>
     29 #include <hardware/hw_auth_token.h>
     30 #include <list>
     31 
     32 namespace keystore {
     33 
     34 class AccessTimeMap {
     35   public:
     36     explicit AccessTimeMap(uint32_t max_size) : max_size_(max_size) {}
     37 
     38     /* If the key is found, returns true and fills \p last_access_time.  If not found returns
     39      * false. */
     40     bool LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const;
     41 
     42     /* Updates the last key access time with the currentTime parameter.  Adds the key if
     43      * needed, returning false if key cannot be added because list is full. */
     44     bool UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout);
     45 
     46   private:
     47     struct AccessTime {
     48         km_id_t keyid;
     49         uint32_t access_time;
     50         uint32_t timeout;
     51     };
     52     std::list<AccessTime> last_access_list_;
     53     const uint32_t max_size_;
     54 };
     55 
     56 class AccessCountMap {
     57   public:
     58     explicit AccessCountMap(uint32_t max_size) : max_size_(max_size) {}
     59 
     60     /* If the key is found, returns true and fills \p count.  If not found returns
     61      * false. */
     62     bool KeyAccessCount(km_id_t keyid, uint32_t* count) const;
     63 
     64     /* Increments key access count, adding an entry if the key has never been used.  Returns
     65      * false if the list has reached maximum size. */
     66     bool IncrementKeyAccessCount(km_id_t keyid);
     67 
     68   private:
     69     struct AccessCount {
     70         km_id_t keyid;
     71         uint64_t access_count;
     72     };
     73     std::list<AccessCount> access_count_list_;
     74     const uint32_t max_size_;
     75 };
     76 
     77 bool is_public_key_algorithm(const AuthorizationSet& auth_set) {
     78     auto algorithm = auth_set.GetTagValue(TAG_ALGORITHM);
     79     return algorithm.isOk() &&
     80            (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC);
     81 }
     82 
     83 static ErrorCode authorized_purpose(const KeyPurpose purpose, const AuthorizationSet& auth_set) {
     84     switch (purpose) {
     85     case KeyPurpose::VERIFY:
     86     case KeyPurpose::ENCRYPT:
     87     case KeyPurpose::SIGN:
     88     case KeyPurpose::DECRYPT:
     89         if (auth_set.Contains(TAG_PURPOSE, purpose)) return ErrorCode::OK;
     90         return ErrorCode::INCOMPATIBLE_PURPOSE;
     91 
     92     default:
     93         return ErrorCode::UNSUPPORTED_PURPOSE;
     94     }
     95 }
     96 
     97 inline bool is_origination_purpose(KeyPurpose purpose) {
     98     return purpose == KeyPurpose::ENCRYPT || purpose == KeyPurpose::SIGN;
     99 }
    100 
    101 inline bool is_usage_purpose(KeyPurpose purpose) {
    102     return purpose == KeyPurpose::DECRYPT || purpose == KeyPurpose::VERIFY;
    103 }
    104 
    105 KeymasterEnforcement::KeymasterEnforcement(uint32_t max_access_time_map_size,
    106                                            uint32_t max_access_count_map_size)
    107     : access_time_map_(new (std::nothrow) AccessTimeMap(max_access_time_map_size)),
    108       access_count_map_(new (std::nothrow) AccessCountMap(max_access_count_map_size)) {}
    109 
    110 KeymasterEnforcement::~KeymasterEnforcement() {
    111     delete access_time_map_;
    112     delete access_count_map_;
    113 }
    114 
    115 ErrorCode KeymasterEnforcement::AuthorizeOperation(const KeyPurpose purpose, const km_id_t keyid,
    116                                                    const AuthorizationSet& auth_set,
    117                                                    const AuthorizationSet& operation_params,
    118                                                    uint64_t op_handle, bool is_begin_operation) {
    119     if (is_public_key_algorithm(auth_set)) {
    120         switch (purpose) {
    121         case KeyPurpose::ENCRYPT:
    122         case KeyPurpose::VERIFY:
    123             /* Public key operations are always authorized. */
    124             return ErrorCode::OK;
    125 
    126         case KeyPurpose::DECRYPT:
    127         case KeyPurpose::SIGN:
    128         case KeyPurpose::DERIVE_KEY:
    129             break;
    130         case KeyPurpose::WRAP_KEY:
    131             return ErrorCode::INCOMPATIBLE_PURPOSE;
    132         };
    133     };
    134 
    135     if (is_begin_operation)
    136         return AuthorizeBegin(purpose, keyid, auth_set, operation_params);
    137     else
    138         return AuthorizeUpdateOrFinish(auth_set, operation_params, op_handle);
    139 }
    140 
    141 // For update and finish the only thing to check is user authentication, and then only if it's not
    142 // timeout-based.
    143 ErrorCode KeymasterEnforcement::AuthorizeUpdateOrFinish(const AuthorizationSet& auth_set,
    144                                                         const AuthorizationSet& operation_params,
    145                                                         uint64_t op_handle) {
    146     int auth_type_index = -1;
    147     for (size_t pos = 0; pos < auth_set.size(); ++pos) {
    148         switch (auth_set[pos].tag) {
    149         case Tag::NO_AUTH_REQUIRED:
    150         case Tag::AUTH_TIMEOUT:
    151             // If no auth is required or if auth is timeout-based, we have nothing to check.
    152             return ErrorCode::OK;
    153 
    154         case Tag::USER_AUTH_TYPE:
    155             auth_type_index = pos;
    156             break;
    157 
    158         default:
    159             break;
    160         }
    161     }
    162 
    163     // Note that at this point we should be able to assume that authentication is required, because
    164     // authentication is required if KM_TAG_NO_AUTH_REQUIRED is absent.  However, there are legacy
    165     // keys which have no authentication-related tags, so we assume that absence is equivalent to
    166     // presence of KM_TAG_NO_AUTH_REQUIRED.
    167     //
    168     // So, if we found KM_TAG_USER_AUTH_TYPE or if we find KM_TAG_USER_SECURE_ID then authentication
    169     // is required.  If we find neither, then we assume authentication is not required and return
    170     // success.
    171     bool authentication_required = (auth_type_index != -1);
    172     for (auto& param : auth_set) {
    173         auto user_secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
    174         if (user_secure_id.isOk()) {
    175             authentication_required = true;
    176             int auth_timeout_index = -1;
    177             if (AuthTokenMatches(auth_set, operation_params, user_secure_id.value(),
    178                                  auth_type_index, auth_timeout_index, op_handle,
    179                                  false /* is_begin_operation */))
    180                 return ErrorCode::OK;
    181         }
    182     }
    183 
    184     if (authentication_required) return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
    185 
    186     return ErrorCode::OK;
    187 }
    188 
    189 ErrorCode KeymasterEnforcement::AuthorizeBegin(const KeyPurpose purpose, const km_id_t keyid,
    190                                                const AuthorizationSet& auth_set,
    191                                                const AuthorizationSet& operation_params) {
    192     // Find some entries that may be needed to handle KM_TAG_USER_SECURE_ID
    193     int auth_timeout_index = -1;
    194     int auth_type_index = -1;
    195     int no_auth_required_index = -1;
    196     for (size_t pos = 0; pos < auth_set.size(); ++pos) {
    197         switch (auth_set[pos].tag) {
    198         case Tag::AUTH_TIMEOUT:
    199             auth_timeout_index = pos;
    200             break;
    201         case Tag::USER_AUTH_TYPE:
    202             auth_type_index = pos;
    203             break;
    204         case Tag::NO_AUTH_REQUIRED:
    205             no_auth_required_index = pos;
    206             break;
    207         default:
    208             break;
    209         }
    210     }
    211 
    212     ErrorCode error = authorized_purpose(purpose, auth_set);
    213     if (error != ErrorCode::OK) return error;
    214 
    215     // If successful, and if key has a min time between ops, this will be set to the time limit
    216     uint32_t min_ops_timeout = UINT32_MAX;
    217 
    218     bool update_access_count = false;
    219     bool caller_nonce_authorized_by_key = false;
    220     bool authentication_required = false;
    221     bool auth_token_matched = false;
    222 
    223     for (auto& param : auth_set) {
    224 
    225         // KM_TAG_PADDING_OLD and KM_TAG_DIGEST_OLD aren't actually members of the enum, so we can't
    226         // switch on them.  There's nothing to validate for them, though, so just ignore them.
    227         if (int32_t(param.tag) == KM_TAG_PADDING_OLD || int32_t(param.tag) == KM_TAG_DIGEST_OLD)
    228             continue;
    229 
    230         switch (param.tag) {
    231 
    232         case Tag::ACTIVE_DATETIME: {
    233             auto date = authorizationValue(TAG_ACTIVE_DATETIME, param);
    234             if (date.isOk() && !activation_date_valid(date.value()))
    235                 return ErrorCode::KEY_NOT_YET_VALID;
    236             break;
    237         }
    238         case Tag::ORIGINATION_EXPIRE_DATETIME: {
    239             auto date = authorizationValue(TAG_ORIGINATION_EXPIRE_DATETIME, param);
    240             if (is_origination_purpose(purpose) && date.isOk() &&
    241                 expiration_date_passed(date.value()))
    242                 return ErrorCode::KEY_EXPIRED;
    243             break;
    244         }
    245         case Tag::USAGE_EXPIRE_DATETIME: {
    246             auto date = authorizationValue(TAG_USAGE_EXPIRE_DATETIME, param);
    247             if (is_usage_purpose(purpose) && date.isOk() && expiration_date_passed(date.value()))
    248                 return ErrorCode::KEY_EXPIRED;
    249             break;
    250         }
    251         case Tag::MIN_SECONDS_BETWEEN_OPS: {
    252             auto min_ops_timeout = authorizationValue(TAG_MIN_SECONDS_BETWEEN_OPS, param);
    253             if (min_ops_timeout.isOk() && !MinTimeBetweenOpsPassed(min_ops_timeout.value(), keyid))
    254                 return ErrorCode::KEY_RATE_LIMIT_EXCEEDED;
    255             break;
    256         }
    257         case Tag::MAX_USES_PER_BOOT: {
    258             auto max_users = authorizationValue(TAG_MAX_USES_PER_BOOT, param);
    259             update_access_count = true;
    260             if (max_users.isOk() && !MaxUsesPerBootNotExceeded(keyid, max_users.value()))
    261                 return ErrorCode::KEY_MAX_OPS_EXCEEDED;
    262             break;
    263         }
    264         case Tag::USER_SECURE_ID:
    265             if (no_auth_required_index != -1) {
    266                 // Key has both KM_TAG_USER_SECURE_ID and KM_TAG_NO_AUTH_REQUIRED
    267                 return ErrorCode::INVALID_KEY_BLOB;
    268             }
    269 
    270             if (auth_timeout_index != -1) {
    271                 auto secure_id = authorizationValue(TAG_USER_SECURE_ID, param);
    272                 authentication_required = true;
    273                 if (secure_id.isOk() &&
    274                     AuthTokenMatches(auth_set, operation_params, secure_id.value(), auth_type_index,
    275                                      auth_timeout_index, 0 /* op_handle */,
    276                                      true /* is_begin_operation */))
    277                     auth_token_matched = true;
    278             }
    279             break;
    280 
    281         case Tag::CALLER_NONCE:
    282             caller_nonce_authorized_by_key = true;
    283             break;
    284 
    285         /* Tags should never be in key auths. */
    286         case Tag::INVALID:
    287         case Tag::AUTH_TOKEN:
    288         case Tag::ROOT_OF_TRUST:
    289         case Tag::APPLICATION_DATA:
    290         case Tag::ATTESTATION_CHALLENGE:
    291         case Tag::ATTESTATION_APPLICATION_ID:
    292         case Tag::ATTESTATION_ID_BRAND:
    293         case Tag::ATTESTATION_ID_DEVICE:
    294         case Tag::ATTESTATION_ID_PRODUCT:
    295         case Tag::ATTESTATION_ID_SERIAL:
    296         case Tag::ATTESTATION_ID_IMEI:
    297         case Tag::ATTESTATION_ID_MEID:
    298         case Tag::ATTESTATION_ID_MANUFACTURER:
    299         case Tag::ATTESTATION_ID_MODEL:
    300             return ErrorCode::INVALID_KEY_BLOB;
    301 
    302         /* Tags used for cryptographic parameters in keygen.  Nothing to enforce. */
    303         case Tag::PURPOSE:
    304         case Tag::ALGORITHM:
    305         case Tag::KEY_SIZE:
    306         case Tag::BLOCK_MODE:
    307         case Tag::DIGEST:
    308         case Tag::MAC_LENGTH:
    309         case Tag::PADDING:
    310         case Tag::NONCE:
    311         case Tag::MIN_MAC_LENGTH:
    312         case Tag::KDF:
    313         case Tag::EC_CURVE:
    314 
    315         /* Tags not used for operations. */
    316         case Tag::BLOB_USAGE_REQUIREMENTS:
    317         case Tag::EXPORTABLE:
    318 
    319         /* Algorithm specific parameters not used for access control. */
    320         case Tag::RSA_PUBLIC_EXPONENT:
    321         case Tag::ECIES_SINGLE_HASH_MODE:
    322 
    323         /* Informational tags. */
    324         case Tag::CREATION_DATETIME:
    325         case Tag::ORIGIN:
    326         case Tag::ROLLBACK_RESISTANT:
    327 
    328         /* Tags handled when KM_TAG_USER_SECURE_ID is handled */
    329         case Tag::NO_AUTH_REQUIRED:
    330         case Tag::USER_AUTH_TYPE:
    331         case Tag::AUTH_TIMEOUT:
    332 
    333         /* Tag to provide data to operations. */
    334         case Tag::ASSOCIATED_DATA:
    335 
    336         /* Tags that are implicitly verified by secure side */
    337         case Tag::ALL_APPLICATIONS:
    338         case Tag::APPLICATION_ID:
    339         case Tag::OS_VERSION:
    340         case Tag::OS_PATCHLEVEL:
    341 
    342         /* Ignored pending removal */
    343         case Tag::USER_ID:
    344         case Tag::ALL_USERS:
    345 
    346         /* TODO(swillden): Handle these */
    347         case Tag::INCLUDE_UNIQUE_ID:
    348         case Tag::UNIQUE_ID:
    349         case Tag::RESET_SINCE_ID_ROTATION:
    350         case Tag::ALLOW_WHILE_ON_BODY:
    351             break;
    352 
    353         case Tag::BOOTLOADER_ONLY:
    354             return ErrorCode::INVALID_KEY_BLOB;
    355         }
    356     }
    357 
    358     if (authentication_required && !auth_token_matched) {
    359         ALOGE("Auth required but no matching auth token found");
    360         return ErrorCode::KEY_USER_NOT_AUTHENTICATED;
    361     }
    362 
    363     if (!caller_nonce_authorized_by_key && is_origination_purpose(purpose) &&
    364         operation_params.Contains(Tag::NONCE))
    365         return ErrorCode::CALLER_NONCE_PROHIBITED;
    366 
    367     if (min_ops_timeout != UINT32_MAX) {
    368         if (!access_time_map_) {
    369             ALOGE("Rate-limited keys table not allocated.  Rate-limited keys disabled");
    370             return ErrorCode::MEMORY_ALLOCATION_FAILED;
    371         }
    372 
    373         if (!access_time_map_->UpdateKeyAccessTime(keyid, get_current_time(), min_ops_timeout)) {
    374             ALOGE("Rate-limited keys table full.  Entries will time out.");
    375             return ErrorCode::TOO_MANY_OPERATIONS;
    376         }
    377     }
    378 
    379     if (update_access_count) {
    380         if (!access_count_map_) {
    381             ALOGE("Usage-count limited keys tabel not allocated.  Count-limited keys disabled");
    382             return ErrorCode::MEMORY_ALLOCATION_FAILED;
    383         }
    384 
    385         if (!access_count_map_->IncrementKeyAccessCount(keyid)) {
    386             ALOGE("Usage count-limited keys table full, until reboot.");
    387             return ErrorCode::TOO_MANY_OPERATIONS;
    388         }
    389     }
    390 
    391     return ErrorCode::OK;
    392 }
    393 
    394 class EvpMdCtx {
    395   public:
    396     EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
    397     ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
    398 
    399     EVP_MD_CTX* get() { return &ctx_; }
    400 
    401   private:
    402     EVP_MD_CTX ctx_;
    403 };
    404 
    405 /* static */
    406 bool KeymasterEnforcement::CreateKeyId(const hidl_vec<uint8_t>& key_blob, km_id_t* keyid) {
    407     EvpMdCtx ctx;
    408 
    409     uint8_t hash[EVP_MAX_MD_SIZE];
    410     unsigned int hash_len;
    411     if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
    412         EVP_DigestUpdate(ctx.get(), &key_blob[0], key_blob.size()) &&
    413         EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
    414         assert(hash_len >= sizeof(*keyid));
    415         memcpy(keyid, hash, sizeof(*keyid));
    416         return true;
    417     }
    418 
    419     return false;
    420 }
    421 
    422 bool KeymasterEnforcement::MinTimeBetweenOpsPassed(uint32_t min_time_between, const km_id_t keyid) {
    423     if (!access_time_map_) return false;
    424 
    425     uint32_t last_access_time;
    426     if (!access_time_map_->LastKeyAccessTime(keyid, &last_access_time)) return true;
    427     return min_time_between <= static_cast<int64_t>(get_current_time()) - last_access_time;
    428 }
    429 
    430 bool KeymasterEnforcement::MaxUsesPerBootNotExceeded(const km_id_t keyid, uint32_t max_uses) {
    431     if (!access_count_map_) return false;
    432 
    433     uint32_t key_access_count;
    434     if (!access_count_map_->KeyAccessCount(keyid, &key_access_count)) return true;
    435     return key_access_count < max_uses;
    436 }
    437 
    438 template <typename IntType, uint32_t byteOrder> struct choose_hton;
    439 
    440 template <typename IntType> struct choose_hton<IntType, __ORDER_LITTLE_ENDIAN__> {
    441     inline static IntType hton(const IntType& value) {
    442         IntType result = 0;
    443         const unsigned char* inbytes = reinterpret_cast<const unsigned char*>(&value);
    444         unsigned char* outbytes = reinterpret_cast<unsigned char*>(&result);
    445         for (int i = sizeof(IntType) - 1; i >= 0; --i) {
    446             *(outbytes++) = inbytes[i];
    447         }
    448         return result;
    449     }
    450 };
    451 
    452 template <typename IntType> struct choose_hton<IntType, __ORDER_BIG_ENDIAN__> {
    453     inline static IntType hton(const IntType& value) { return value; }
    454 };
    455 
    456 template <typename IntType> inline IntType hton(const IntType& value) {
    457     return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
    458 }
    459 
    460 template <typename IntType> inline IntType ntoh(const IntType& value) {
    461     // same operation and hton
    462     return choose_hton<IntType, __BYTE_ORDER__>::hton(value);
    463 }
    464 
    465 bool KeymasterEnforcement::AuthTokenMatches(const AuthorizationSet& auth_set,
    466                                             const AuthorizationSet& operation_params,
    467                                             const uint64_t user_secure_id,
    468                                             const int auth_type_index, const int auth_timeout_index,
    469                                             const uint64_t op_handle,
    470                                             bool is_begin_operation) const {
    471     assert(auth_type_index < static_cast<int>(auth_set.size()));
    472     assert(auth_timeout_index < static_cast<int>(auth_set.size()));
    473 
    474     auto auth_token_blob = operation_params.GetTagValue(TAG_AUTH_TOKEN);
    475     if (!auth_token_blob.isOk()) {
    476         ALOGE("Authentication required, but auth token not provided");
    477         return false;
    478     }
    479 
    480     if (auth_token_blob.value().size() != sizeof(hw_auth_token_t)) {
    481         ALOGE("Bug: Auth token is the wrong size (%zu expected, %zu found)",
    482               sizeof(hw_auth_token_t), auth_token_blob.value().size());
    483         return false;
    484     }
    485 
    486     hw_auth_token_t auth_token;
    487     memcpy(&auth_token, &auth_token_blob.value()[0], sizeof(hw_auth_token_t));
    488     if (auth_token.version != HW_AUTH_TOKEN_VERSION) {
    489         ALOGE("Bug: Auth token is the version %hhu (or is not an auth token). Expected %d",
    490               auth_token.version, HW_AUTH_TOKEN_VERSION);
    491         return false;
    492     }
    493 
    494     if (!ValidateTokenSignature(auth_token)) {
    495         ALOGE("Auth token signature invalid");
    496         return false;
    497     }
    498 
    499     if (auth_timeout_index == -1 && op_handle && op_handle != auth_token.challenge) {
    500         ALOGE("Auth token has the challenge %" PRIu64 ", need %" PRIu64, auth_token.challenge,
    501               op_handle);
    502         return false;
    503     }
    504 
    505     if (user_secure_id != auth_token.user_id && user_secure_id != auth_token.authenticator_id) {
    506         ALOGI("Auth token SIDs %" PRIu64 " and %" PRIu64 " do not match key SID %" PRIu64,
    507               auth_token.user_id, auth_token.authenticator_id, user_secure_id);
    508         return false;
    509     }
    510 
    511     if (auth_type_index < 0 || auth_type_index > static_cast<int>(auth_set.size())) {
    512         ALOGE("Auth required but no auth type found");
    513         return false;
    514     }
    515 
    516     assert(auth_set[auth_type_index].tag == KM_TAG_USER_AUTH_TYPE);
    517     auto key_auth_type_mask = authorizationValue(TAG_USER_AUTH_TYPE, auth_set[auth_type_index]);
    518     if (!key_auth_type_mask.isOk()) return false;
    519 
    520     uint32_t token_auth_type = ntoh(auth_token.authenticator_type);
    521     if ((uint32_t(key_auth_type_mask.value()) & token_auth_type) == 0) {
    522         ALOGE("Key requires match of auth type mask 0%uo, but token contained 0%uo",
    523               key_auth_type_mask.value(), token_auth_type);
    524         return false;
    525     }
    526 
    527     if (auth_timeout_index != -1 && is_begin_operation) {
    528         assert(auth_set[auth_timeout_index].tag == KM_TAG_AUTH_TIMEOUT);
    529         auto auth_token_timeout =
    530             authorizationValue(TAG_AUTH_TIMEOUT, auth_set[auth_timeout_index]);
    531         if (!auth_token_timeout.isOk()) return false;
    532 
    533         if (auth_token_timed_out(auth_token, auth_token_timeout.value())) {
    534             ALOGE("Auth token has timed out");
    535             return false;
    536         }
    537     }
    538 
    539     // Survived the whole gauntlet.  We have authentage!
    540     return true;
    541 }
    542 
    543 bool AccessTimeMap::LastKeyAccessTime(km_id_t keyid, uint32_t* last_access_time) const {
    544     for (auto& entry : last_access_list_)
    545         if (entry.keyid == keyid) {
    546             *last_access_time = entry.access_time;
    547             return true;
    548         }
    549     return false;
    550 }
    551 
    552 bool AccessTimeMap::UpdateKeyAccessTime(km_id_t keyid, uint32_t current_time, uint32_t timeout) {
    553     for (auto iter = last_access_list_.begin(); iter != last_access_list_.end();) {
    554         if (iter->keyid == keyid) {
    555             iter->access_time = current_time;
    556             return true;
    557         }
    558 
    559         // Expire entry if possible.
    560         assert(current_time >= iter->access_time);
    561         if (current_time - iter->access_time >= iter->timeout)
    562             iter = last_access_list_.erase(iter);
    563         else
    564             ++iter;
    565     }
    566 
    567     if (last_access_list_.size() >= max_size_) return false;
    568 
    569     AccessTime new_entry;
    570     new_entry.keyid = keyid;
    571     new_entry.access_time = current_time;
    572     new_entry.timeout = timeout;
    573     last_access_list_.push_front(new_entry);
    574     return true;
    575 }
    576 
    577 bool AccessCountMap::KeyAccessCount(km_id_t keyid, uint32_t* count) const {
    578     for (auto& entry : access_count_list_)
    579         if (entry.keyid == keyid) {
    580             *count = entry.access_count;
    581             return true;
    582         }
    583     return false;
    584 }
    585 
    586 bool AccessCountMap::IncrementKeyAccessCount(km_id_t keyid) {
    587     for (auto& entry : access_count_list_)
    588         if (entry.keyid == keyid) {
    589             // Note that the 'if' below will always be true because KM_TAG_MAX_USES_PER_BOOT is a
    590             // uint32_t, and as soon as entry.access_count reaches the specified maximum value
    591             // operation requests will be rejected and access_count won't be incremented any more.
    592             // And, besides, UINT64_MAX is huge.  But we ensure that it doesn't wrap anyway, out of
    593             // an abundance of caution.
    594             if (entry.access_count < UINT64_MAX) ++entry.access_count;
    595             return true;
    596         }
    597 
    598     if (access_count_list_.size() >= max_size_) return false;
    599 
    600     AccessCount new_entry;
    601     new_entry.keyid = keyid;
    602     new_entry.access_count = 1;
    603     access_count_list_.push_front(new_entry);
    604     return true;
    605 }
    606 }; /* namespace keystore */
    607