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