blob: 4727015f25f59b7cf30ea479400b247ef0ad4379 [file] [log] [blame]
Matthew Maurerd7815ca2021-05-06 21:58:45 -07001// Copyright 2021, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! This module implements a per-boot, shared, in-memory storage of auth tokens
Eric Biggersb5613da2024-03-13 19:31:42 +000016//! for the main Keystore 2.0 database module.
Matthew Maurerd7815ca2021-05-06 21:58:45 -070017
Eric Biggersb5613da2024-03-13 19:31:42 +000018use super::AuthTokenEntry;
Matthew Maurerd7815ca2021-05-06 21:58:45 -070019use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
20 HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
21};
22use lazy_static::lazy_static;
23use std::collections::HashSet;
Matthew Maurerd7815ca2021-05-06 21:58:45 -070024use std::sync::Arc;
25use std::sync::RwLock;
26
27#[derive(PartialEq, PartialOrd, Ord, Eq, Hash)]
28struct AuthTokenId {
29 user_id: i64,
30 auth_id: i64,
31 authenticator_type: HardwareAuthenticatorType,
32}
33
34impl AuthTokenId {
35 fn from_auth_token(tok: &HardwareAuthToken) -> Self {
36 AuthTokenId {
37 user_id: tok.userId,
38 auth_id: tok.authenticatorId,
39 authenticator_type: tok.authenticatorType,
40 }
41 }
42}
43
44//Implements Eq/Hash to only operate on the AuthTokenId portion
45//of the AuthTokenEntry. This allows a HashSet to DTRT.
46#[derive(Clone)]
47struct AuthTokenEntryWrap(AuthTokenEntry);
48
49impl std::hash::Hash for AuthTokenEntryWrap {
50 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
51 AuthTokenId::from_auth_token(&self.0.auth_token).hash(state)
52 }
53}
54
55impl PartialEq<AuthTokenEntryWrap> for AuthTokenEntryWrap {
56 fn eq(&self, other: &AuthTokenEntryWrap) -> bool {
57 AuthTokenId::from_auth_token(&self.0.auth_token)
58 == AuthTokenId::from_auth_token(&other.0.auth_token)
59 }
60}
61
62impl Eq for AuthTokenEntryWrap {}
63
Eric Biggersb5613da2024-03-13 19:31:42 +000064/// Per-boot state structure. Currently only used to track auth tokens.
Matthew Maurerd7815ca2021-05-06 21:58:45 -070065#[derive(Default)]
66pub struct PerbootDB {
67 // We can use a .unwrap() discipline on this lock, because only panicking
68 // while holding a .write() lock will poison it. The only write usage is
69 // an insert call which inserts a pre-constructed pair.
70 auth_tokens: RwLock<HashSet<AuthTokenEntryWrap>>,
Matthew Maurerd7815ca2021-05-06 21:58:45 -070071}
72
73lazy_static! {
74 /// The global instance of the perboot DB. Located here rather than in globals
75 /// in order to restrict access to the database module.
76 pub static ref PERBOOT_DB: Arc<PerbootDB> = Arc::new(PerbootDB::new());
77}
78
79impl PerbootDB {
80 /// Construct a new perboot database. Currently just uses default values.
81 pub fn new() -> Self {
82 Default::default()
83 }
84 /// Add a new auth token + timestamp to the database, replacing any which
85 /// match all of user_id, auth_id, and auth_type.
86 pub fn insert_auth_token_entry(&self, entry: AuthTokenEntry) {
87 self.auth_tokens.write().unwrap().replace(AuthTokenEntryWrap(entry));
88 }
89 /// Locate an auth token entry which matches the predicate with the most
90 /// recent update time.
91 pub fn find_auth_token_entry<P: Fn(&AuthTokenEntry) -> bool>(
92 &self,
93 p: P,
94 ) -> Option<AuthTokenEntry> {
95 let reader = self.auth_tokens.read().unwrap();
96 let mut matches: Vec<_> = reader.iter().filter(|x| p(&x.0)).collect();
97 matches.sort_by_key(|x| x.0.time_received);
98 matches.last().map(|x| x.0.clone())
99 }
Matthew Maurerd7815ca2021-05-06 21:58:45 -0700100 /// Return how many auth tokens are currently tracked.
101 pub fn auth_tokens_len(&self) -> usize {
102 self.auth_tokens.read().unwrap().len()
103 }
104 #[cfg(test)]
105 /// For testing, return all auth tokens currently tracked.
106 pub fn get_all_auth_token_entries(&self) -> Vec<AuthTokenEntry> {
107 self.auth_tokens.read().unwrap().iter().cloned().map(|x| x.0).collect()
108 }
109}