Keystore 2.0: Move per-boot database out of SQLite
Being in SQLite incurs a variety of overheads. Originally, the per-boot
database was in SQLite with the intention of living in a temporary file
to allow keystore2 to restart without losing auth token state. Since
keystore2 is not allowed to crash, it was moved to an in-memory SQLite
database. Since it is no longer vfs backed, we do not need to pay the
memory, speed, and complexity costs of SQLite for it any longer.
Bug: 186436093
Test: atest keystore2_test
Test: atest CtsKeystoreTestCases
Change-Id: I5c219d294af1876a18a7fdef40307f3b92ae4b8b
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index d07dab5..777089f 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -121,7 +121,7 @@
// Check keystore permission.
check_keystore_permission(KeystorePerm::add_auth()).context("In add_auth_token.")?;
- ENFORCEMENTS.add_auth_token(auth_token.clone())?;
+ ENFORCEMENTS.add_auth_token(auth_token.clone());
Ok(())
}
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 28ff02d..4ab4258 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -41,6 +41,8 @@
//! from the database module these functions take permission check
//! callbacks.
+mod perboot;
+
use crate::impl_metadata; // This is in db_utils.rs
use crate::key_parameter::{KeyParameter, Tag};
use crate::permission::KeyPermSet;
@@ -61,9 +63,6 @@
HardwareAuthToken::HardwareAuthToken,
HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel,
};
-use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
- Timestamp::Timestamp,
-};
use android_system_keystore2::aidl::android::system::keystore2::{
Domain::Domain, KeyDescriptor::KeyDescriptor,
};
@@ -734,6 +733,7 @@
pub struct KeystoreDB {
conn: Connection,
gc: Option<Arc<Gc>>,
+ perboot: Arc<perboot::PerbootDB>,
}
/// Database representation of the monotonic time retrieved from the system call clock_gettime with
@@ -782,6 +782,7 @@
/// This struct encapsulates the information to be stored in the database about the auth tokens
/// received by keystore.
+#[derive(Clone)]
pub struct AuthTokenEntry {
auth_token: HardwareAuthToken,
time_received: MonotonicRawTime,
@@ -828,21 +829,10 @@
impl KeystoreDB {
const UNASSIGNED_KEY_ID: i64 = -1i64;
- const PERBOOT_DB_FILE_NAME: &'static str = &"file:perboot.sqlite?mode=memory&cache=shared";
/// Name of the file that holds the cross-boot persistent database.
pub const PERSISTENT_DB_FILENAME: &'static str = &"persistent.sqlite";
- /// This creates a PerBootDbKeepAlive object to keep the per boot database alive.
- pub fn keep_perboot_db_alive() -> Result<PerBootDbKeepAlive> {
- let conn = Connection::open_in_memory()
- .context("In keep_perboot_db_alive: Failed to initialize SQLite connection.")?;
-
- conn.execute("ATTACH DATABASE ? as perboot;", params![Self::PERBOOT_DB_FILE_NAME])
- .context("In keep_perboot_db_alive: Failed to attach database perboot.")?;
- Ok(PerBootDbKeepAlive(conn))
- }
-
/// This will create a new database connection connecting the two
/// files persistent.sqlite and perboot.sqlite in the given directory.
/// It also attempts to initialize all of the tables.
@@ -859,12 +849,12 @@
let mut persistent_path_str = "file:".to_owned();
persistent_path_str.push_str(&persistent_path.to_string_lossy());
- let conn = Self::make_connection(&persistent_path_str, &Self::PERBOOT_DB_FILE_NAME)?;
+ let conn = Self::make_connection(&persistent_path_str)?;
// On busy fail Immediately. It is unlikely to succeed given a bug in sqlite.
conn.busy_handler(None).context("In KeystoreDB::new: Failed to set busy handler.")?;
- let mut db = Self { conn, gc };
+ let mut db = Self { conn, gc, perboot: perboot::PERBOOT_DB.clone() };
db.with_transaction(TransactionBehavior::Immediate, |tx| {
Self::init_tables(tx).context("Trying to initialize tables.").no_gc()
})?;
@@ -978,41 +968,10 @@
)
.context("Failed to initialize \"grant\" table.")?;
- //TODO: only drop the following two perboot tables if this is the first start up
- //during the boot (b/175716626).
- // tx.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
- // .context("Failed to drop perboot.authtoken table")?;
- tx.execute(
- "CREATE TABLE IF NOT EXISTS perboot.authtoken (
- id INTEGER PRIMARY KEY,
- challenge INTEGER,
- user_id INTEGER,
- auth_id INTEGER,
- authenticator_type INTEGER,
- timestamp INTEGER,
- mac BLOB,
- time_received INTEGER,
- UNIQUE(user_id, auth_id, authenticator_type));",
- NO_PARAMS,
- )
- .context("Failed to initialize \"authtoken\" table.")?;
-
- // tx.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
- // .context("Failed to drop perboot.metadata table")?;
- // metadata table stores certain miscellaneous information required for keystore functioning
- // during a boot cycle, as key-value pairs.
- tx.execute(
- "CREATE TABLE IF NOT EXISTS perboot.metadata (
- key TEXT,
- value BLOB,
- UNIQUE(key));",
- NO_PARAMS,
- )
- .context("Failed to initialize \"metadata\" table.")?;
Ok(())
}
- fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
+ fn make_connection(persistent_file: &str) -> Result<Connection> {
let conn =
Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
@@ -1030,26 +989,10 @@
}
break;
}
- loop {
- if let Err(e) = conn
- .execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
- .context("Failed to attach database perboot.")
- {
- if Self::is_locked_error(&e) {
- std::thread::sleep(std::time::Duration::from_micros(500));
- continue;
- } else {
- return Err(e);
- }
- }
- break;
- }
// Drop the cache size from default (2M) to 0.5M
conn.execute("PRAGMA persistent.cache_size = -500;", params![])
.context("Failed to decrease cache size for persistent db")?;
- conn.execute("PRAGMA perboot.cache_size = -500;", params![])
- .context("Failed to decrease cache size for perboot db")?;
Ok(conn)
}
@@ -1135,7 +1078,15 @@
}
StatsdStorageType::Grant => self.get_table_size(storage_type, "persistent", "grant"),
StatsdStorageType::AuthToken => {
- self.get_table_size(storage_type, "perboot", "authtoken")
+ // Since the table is actually a BTreeMap now, unused_size is not meaningfully
+ // reportable
+ // Size provided is only an approximation
+ Ok(Keystore2StorageStats {
+ storage_type,
+ size: (self.perboot.auth_tokens_len() * std::mem::size_of::<AuthTokenEntry>())
+ as i64,
+ unused_size: 0,
+ })
}
StatsdStorageType::BlobMetadata => {
self.get_table_size(storage_type, "persistent", "blobmetadata")
@@ -3177,110 +3128,35 @@
}
}
- /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
- pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
- let _wp = wd::watch_millis("KeystoreDB::insert_auth_token", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- tx.execute(
- "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
- authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
- params![
- auth_token.challenge,
- auth_token.userId,
- auth_token.authenticatorId,
- auth_token.authenticatorType.0 as i32,
- auth_token.timestamp.milliSeconds as i64,
- auth_token.mac,
- MonotonicRawTime::now(),
- ],
- )
- .context("In insert_auth_token: failed to insert auth token into the database")?;
- Ok(()).no_gc()
- })
+ /// Insert or replace the auth token based on (user_id, auth_id, auth_type)
+ pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) {
+ self.perboot.insert_auth_token_entry(AuthTokenEntry::new(
+ auth_token.clone(),
+ MonotonicRawTime::now(),
+ ))
}
/// Find the newest auth token matching the given predicate.
- pub fn find_auth_token_entry<F>(
- &mut self,
- p: F,
- ) -> Result<Option<(AuthTokenEntry, MonotonicRawTime)>>
+ pub fn find_auth_token_entry<F>(&self, p: F) -> Option<(AuthTokenEntry, MonotonicRawTime)>
where
F: Fn(&AuthTokenEntry) -> bool,
{
- let _wp = wd::watch_millis("KeystoreDB::find_auth_token_entry", 500);
-
- self.with_transaction(TransactionBehavior::Deferred, |tx| {
- let mut stmt = tx
- .prepare("SELECT * from perboot.authtoken ORDER BY time_received DESC;")
- .context("Prepare statement failed.")?;
-
- let mut rows = stmt.query(NO_PARAMS).context("Failed to query.")?;
-
- while let Some(row) = rows.next().context("Failed to get next row.")? {
- let entry = AuthTokenEntry::new(
- HardwareAuthToken {
- challenge: row.get(1)?,
- userId: row.get(2)?,
- authenticatorId: row.get(3)?,
- authenticatorType: HardwareAuthenticatorType(row.get(4)?),
- timestamp: Timestamp { milliSeconds: row.get(5)? },
- mac: row.get(6)?,
- },
- row.get(7)?,
- );
- if p(&entry) {
- return Ok(Some((
- entry,
- Self::get_last_off_body(tx)
- .context("In find_auth_token_entry: Trying to get last off body")?,
- )))
- .no_gc();
- }
- }
- Ok(None).no_gc()
- })
- .context("In find_auth_token_entry.")
+ self.perboot.find_auth_token_entry(p).map(|entry| (entry, self.get_last_off_body()))
}
/// Insert last_off_body into the metadata table at the initialization of auth token table
- pub fn insert_last_off_body(&mut self, last_off_body: MonotonicRawTime) -> Result<()> {
- let _wp = wd::watch_millis("KeystoreDB::insert_last_off_body", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- tx.execute(
- "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
- params!["last_off_body", last_off_body],
- )
- .context("In insert_last_off_body: failed to insert.")?;
- Ok(()).no_gc()
- })
+ pub fn insert_last_off_body(&self, last_off_body: MonotonicRawTime) {
+ self.perboot.set_last_off_body(last_off_body)
}
/// Update last_off_body when on_device_off_body is called
- pub fn update_last_off_body(&mut self, last_off_body: MonotonicRawTime) -> Result<()> {
- let _wp = wd::watch_millis("KeystoreDB::update_last_off_body", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- tx.execute(
- "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
- params![last_off_body, "last_off_body"],
- )
- .context("In update_last_off_body: failed to update.")?;
- Ok(()).no_gc()
- })
+ pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) {
+ self.perboot.set_last_off_body(last_off_body)
}
/// Get last_off_body time when finding auth tokens
- fn get_last_off_body(tx: &Transaction) -> Result<MonotonicRawTime> {
- let _wp = wd::watch_millis("KeystoreDB::get_last_off_body", 500);
-
- tx.query_row(
- "SELECT value from perboot.metadata WHERE key = ?;",
- params!["last_off_body"],
- |row| row.get(0),
- )
- .context("In get_last_off_body: query_row failed.")
+ fn get_last_off_body(&self) -> MonotonicRawTime {
+ self.perboot.get_last_off_body()
}
}
@@ -3304,7 +3180,7 @@
Timestamp::Timestamp,
};
use rusqlite::NO_PARAMS;
- use rusqlite::{Error, TransactionBehavior};
+ use rusqlite::TransactionBehavior;
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fmt::Write;
@@ -3316,9 +3192,9 @@
use std::time::Instant;
fn new_test_db() -> Result<KeystoreDB> {
- let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
+ let conn = KeystoreDB::make_connection("file::memory:")?;
- let mut db = KeystoreDB { conn, gc: None };
+ let mut db = KeystoreDB { conn, gc: None, perboot: Arc::new(perboot::PerbootDB::new()) };
db.with_transaction(TransactionBehavior::Immediate, |tx| {
KeystoreDB::init_tables(tx).context("Failed to initialize tables.").no_gc()
})?;
@@ -3404,15 +3280,6 @@
assert_eq!(tables[3], "keyentry");
assert_eq!(tables[4], "keymetadata");
assert_eq!(tables[5], "keyparameter");
- let tables = db
- .conn
- .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
- .query_map(params![], |row| row.get(0))?
- .collect::<rusqlite::Result<Vec<String>>>()?;
-
- assert_eq!(tables.len(), 2);
- assert_eq!(tables[0], "authtoken");
- assert_eq!(tables[1], "metadata");
Ok(())
}
@@ -3427,8 +3294,8 @@
timestamp: Timestamp { milliSeconds: 500 },
mac: String::from("mac").into_bytes(),
};
- db.insert_auth_token(&auth_token1)?;
- let auth_tokens_returned = get_auth_tokens(&mut db)?;
+ db.insert_auth_token(&auth_token1);
+ let auth_tokens_returned = get_auth_tokens(&db);
assert_eq!(auth_tokens_returned.len(), 1);
// insert another auth token with the same values for the columns in the UNIQUE constraint
@@ -3442,8 +3309,8 @@
mac: String::from("mac").into_bytes(),
};
- db.insert_auth_token(&auth_token2)?;
- let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
+ db.insert_auth_token(&auth_token2);
+ let mut auth_tokens_returned = get_auth_tokens(&db);
assert_eq!(auth_tokens_returned.len(), 1);
if let Some(auth_token) = auth_tokens_returned.pop() {
@@ -3461,33 +3328,16 @@
mac: String::from("mac").into_bytes(),
};
- db.insert_auth_token(&auth_token3)?;
- let auth_tokens_returned = get_auth_tokens(&mut db)?;
+ db.insert_auth_token(&auth_token3);
+ let auth_tokens_returned = get_auth_tokens(&db);
assert_eq!(auth_tokens_returned.len(), 2);
Ok(())
}
// utility function for test_auth_token_table_invariant()
- fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
- let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
-
- let auth_token_entries: Vec<AuthTokenEntry> = stmt
- .query_map(NO_PARAMS, |row| {
- Ok(AuthTokenEntry::new(
- HardwareAuthToken {
- challenge: row.get(1)?,
- userId: row.get(2)?,
- authenticatorId: row.get(3)?,
- authenticatorType: HardwareAuthenticatorType(row.get(4)?),
- timestamp: Timestamp { milliSeconds: row.get(5)? },
- mac: row.get(6)?,
- },
- row.get(7)?,
- ))
- })?
- .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
- Ok(auth_token_entries)
+ fn get_auth_tokens(db: &KeystoreDB) -> Vec<AuthTokenEntry> {
+ db.perboot.get_all_auth_token_entries()
}
#[test]
@@ -5341,16 +5191,16 @@
#[test]
fn test_last_off_body() -> Result<()> {
let mut db = new_test_db()?;
- db.insert_last_off_body(MonotonicRawTime::now())?;
+ db.insert_last_off_body(MonotonicRawTime::now());
let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
- let last_off_body_1 = KeystoreDB::get_last_off_body(&tx)?;
tx.commit()?;
+ let last_off_body_1 = db.get_last_off_body();
let one_second = Duration::from_secs(1);
thread::sleep(one_second);
- db.update_last_off_body(MonotonicRawTime::now())?;
+ db.update_last_off_body(MonotonicRawTime::now());
let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
- let last_off_body_2 = KeystoreDB::get_last_off_body(&tx2)?;
tx2.commit()?;
+ let last_off_body_2 = db.get_last_off_body();
assert!(last_off_body_1.seconds() < last_off_body_2.seconds());
Ok(())
}
@@ -5437,7 +5287,12 @@
for t in get_valid_statsd_storage_types() {
let stat = db.get_storage_stat(t)?;
- assert!(stat.size >= PAGE_SIZE);
+ // AuthToken can be less than a page since it's in a btree, not sqlite
+ // TODO(b/187474736) stop using if-let here
+ if let StatsdStorageType::AuthToken = t {
+ } else {
+ assert!(stat.size >= PAGE_SIZE);
+ }
assert!(stat.size >= stat.unused_size);
}
@@ -5567,7 +5422,7 @@
authenticatorType: kmhw_authenticator_type::ANY,
timestamp: Timestamp { milliSeconds: 10 },
mac: b"mac".to_vec(),
- })?;
+ });
assert_storage_increased(&mut db, vec![StatsdStorageType::AuthToken], &mut working_stats);
Ok(())
}
@@ -5596,4 +5451,40 @@
Ok(())
}
+
+ #[test]
+ fn find_auth_token_entry_returns_latest() -> Result<()> {
+ let mut db = new_test_db()?;
+ db.insert_auth_token(&HardwareAuthToken {
+ challenge: 123,
+ userId: 456,
+ authenticatorId: 789,
+ authenticatorType: kmhw_authenticator_type::ANY,
+ timestamp: Timestamp { milliSeconds: 10 },
+ mac: b"mac0".to_vec(),
+ });
+ std::thread::sleep(std::time::Duration::from_millis(1));
+ db.insert_auth_token(&HardwareAuthToken {
+ challenge: 123,
+ userId: 457,
+ authenticatorId: 789,
+ authenticatorType: kmhw_authenticator_type::ANY,
+ timestamp: Timestamp { milliSeconds: 12 },
+ mac: b"mac1".to_vec(),
+ });
+ std::thread::sleep(std::time::Duration::from_millis(1));
+ db.insert_auth_token(&HardwareAuthToken {
+ challenge: 123,
+ userId: 458,
+ authenticatorId: 789,
+ authenticatorType: kmhw_authenticator_type::ANY,
+ timestamp: Timestamp { milliSeconds: 3 },
+ mac: b"mac2".to_vec(),
+ });
+ // All three entries are in the database
+ assert_eq!(db.perboot.auth_tokens_len(), 3);
+ // It selected the most recent timestamp
+ assert_eq!(db.find_auth_token_entry(|_| true).unwrap().0.auth_token.mac, b"mac2".to_vec());
+ Ok(())
+ }
}
diff --git a/keystore2/src/database/perboot.rs b/keystore2/src/database/perboot.rs
new file mode 100644
index 0000000..7ff35fa
--- /dev/null
+++ b/keystore2/src/database/perboot.rs
@@ -0,0 +1,122 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements a per-boot, shared, in-memory storage of auth tokens
+//! and last-time-on-body for the main Keystore 2.0 database module.
+
+use super::{AuthTokenEntry, MonotonicRawTime};
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+ HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
+};
+use lazy_static::lazy_static;
+use std::collections::HashSet;
+use std::sync::atomic::{AtomicI64, Ordering};
+use std::sync::Arc;
+use std::sync::RwLock;
+
+#[derive(PartialEq, PartialOrd, Ord, Eq, Hash)]
+struct AuthTokenId {
+ user_id: i64,
+ auth_id: i64,
+ authenticator_type: HardwareAuthenticatorType,
+}
+
+impl AuthTokenId {
+ fn from_auth_token(tok: &HardwareAuthToken) -> Self {
+ AuthTokenId {
+ user_id: tok.userId,
+ auth_id: tok.authenticatorId,
+ authenticator_type: tok.authenticatorType,
+ }
+ }
+}
+
+//Implements Eq/Hash to only operate on the AuthTokenId portion
+//of the AuthTokenEntry. This allows a HashSet to DTRT.
+#[derive(Clone)]
+struct AuthTokenEntryWrap(AuthTokenEntry);
+
+impl std::hash::Hash for AuthTokenEntryWrap {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ AuthTokenId::from_auth_token(&self.0.auth_token).hash(state)
+ }
+}
+
+impl PartialEq<AuthTokenEntryWrap> for AuthTokenEntryWrap {
+ fn eq(&self, other: &AuthTokenEntryWrap) -> bool {
+ AuthTokenId::from_auth_token(&self.0.auth_token)
+ == AuthTokenId::from_auth_token(&other.0.auth_token)
+ }
+}
+
+impl Eq for AuthTokenEntryWrap {}
+
+/// Per-boot state structure. Currently only used to track auth tokens and
+/// last-off-body.
+#[derive(Default)]
+pub struct PerbootDB {
+ // We can use a .unwrap() discipline on this lock, because only panicking
+ // while holding a .write() lock will poison it. The only write usage is
+ // an insert call which inserts a pre-constructed pair.
+ auth_tokens: RwLock<HashSet<AuthTokenEntryWrap>>,
+ // Ordering::Relaxed is appropriate for accessing this atomic, since it
+ // does not currently need to be synchronized with anything else.
+ last_off_body: AtomicI64,
+}
+
+lazy_static! {
+ /// The global instance of the perboot DB. Located here rather than in globals
+ /// in order to restrict access to the database module.
+ pub static ref PERBOOT_DB: Arc<PerbootDB> = Arc::new(PerbootDB::new());
+}
+
+impl PerbootDB {
+ /// Construct a new perboot database. Currently just uses default values.
+ pub fn new() -> Self {
+ Default::default()
+ }
+ /// Add a new auth token + timestamp to the database, replacing any which
+ /// match all of user_id, auth_id, and auth_type.
+ pub fn insert_auth_token_entry(&self, entry: AuthTokenEntry) {
+ self.auth_tokens.write().unwrap().replace(AuthTokenEntryWrap(entry));
+ }
+ /// Locate an auth token entry which matches the predicate with the most
+ /// recent update time.
+ pub fn find_auth_token_entry<P: Fn(&AuthTokenEntry) -> bool>(
+ &self,
+ p: P,
+ ) -> Option<AuthTokenEntry> {
+ let reader = self.auth_tokens.read().unwrap();
+ let mut matches: Vec<_> = reader.iter().filter(|x| p(&x.0)).collect();
+ matches.sort_by_key(|x| x.0.time_received);
+ matches.last().map(|x| x.0.clone())
+ }
+ /// Get the last time the device was off the user's body
+ pub fn get_last_off_body(&self) -> MonotonicRawTime {
+ MonotonicRawTime(self.last_off_body.load(Ordering::Relaxed))
+ }
+ /// Set the last time the device was off the user's body
+ pub fn set_last_off_body(&self, last_off_body: MonotonicRawTime) {
+ self.last_off_body.store(last_off_body.0, Ordering::Relaxed)
+ }
+ /// Return how many auth tokens are currently tracked.
+ pub fn auth_tokens_len(&self) -> usize {
+ self.auth_tokens.read().unwrap().len()
+ }
+ #[cfg(test)]
+ /// For testing, return all auth tokens currently tracked.
+ pub fn get_all_auth_token_entries(&self) -> Vec<AuthTokenEntry> {
+ self.auth_tokens.read().unwrap().iter().cloned().map(|x| x.0).collect()
+ }
+}
diff --git a/keystore2/src/enforcements.rs b/keystore2/src/enforcements.rs
index 04d1f77..8bf2090 100644
--- a/keystore2/src/enforcements.rs
+++ b/keystore2/src/enforcements.rs
@@ -638,8 +638,7 @@
} else {
unlocked_device_required
}
- })
- .context("In authorize_create: Trying to get required auth token.")?;
+ });
Some(
hat_and_last_off_body
.ok_or(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
@@ -700,15 +699,11 @@
})
}
- fn find_auth_token<F>(p: F) -> Result<Option<(AuthTokenEntry, MonotonicRawTime)>>
+ fn find_auth_token<F>(p: F) -> Option<(AuthTokenEntry, MonotonicRawTime)>
where
F: Fn(&AuthTokenEntry) -> bool,
{
- DB.with(|db| {
- let mut db = db.borrow_mut();
- db.find_auth_token_entry(p).context("Trying to find auth token.")
- })
- .context("In find_auth_token.")
+ DB.with(|db| db.borrow().find_auth_token_entry(p))
}
/// Checks if the time now since epoch is greater than (or equal, if is_given_time_inclusive is
@@ -752,11 +747,9 @@
/// Add this auth token to the database.
/// Then present the auth token to the op auth map. If an operation is waiting for this
/// auth token this fulfills the request and removes the receiver from the map.
- pub fn add_auth_token(&self, hat: HardwareAuthToken) -> Result<()> {
- DB.with(|db| db.borrow_mut().insert_auth_token(&hat)).context("In add_auth_token.")?;
-
+ pub fn add_auth_token(&self, hat: HardwareAuthToken) {
+ DB.with(|db| db.borrow_mut().insert_auth_token(&hat));
self.op_auth_map.add_auth_token(hat);
- Ok(())
}
/// This allows adding an entry to the op_auth_map, indexed by the operation challenge.
@@ -824,10 +817,7 @@
// Filter the matching auth tokens by challenge
let result = Self::find_auth_token(|hat: &AuthTokenEntry| {
(challenge == hat.challenge()) && hat.satisfies(&sids, auth_type)
- })
- .context(
- "In get_auth_tokens: Failed to get a matching auth token filtered by challenge.",
- )?;
+ });
let auth_token = if let Some((auth_token_entry, _)) = result {
auth_token_entry.take_auth_token()
@@ -842,10 +832,7 @@
auth_token_max_age_millis > token_age_in_millis
});
token_valid && auth_token_entry.satisfies(&sids, auth_type)
- })
- .context(
- "In get_auth_tokens: Failed to get a matching auth token filtered by age.",
- )?;
+ });
if let Some((auth_token_entry, _)) = result {
auth_token_entry.take_auth_token()
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index c492120..8d39b22 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -61,8 +61,7 @@
.expect("Failed to open database.");
DB_INIT.call_once(|| {
log::info!("Touching Keystore 2.0 database for this first time since boot.");
- db.insert_last_off_body(MonotonicRawTime::now())
- .expect("Could not initialize database with last off body.");
+ db.insert_last_off_body(MonotonicRawTime::now());
log::info!("Calling cleanup leftovers.");
let n = db.cleanup_leftovers().expect("Failed to cleanup database on startup.");
if n != 0 {
diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
index 4d4a718..29330a6 100644
--- a/keystore2/src/keystore2_main.rs
+++ b/keystore2/src/keystore2_main.rs
@@ -47,10 +47,6 @@
// Saying hi.
info!("Keystore2 is starting.");
- // Initialize the per boot database.
- let _keep_me_alive = keystore2::database::KeystoreDB::keep_perboot_db_alive()
- .expect("Failed to initialize the perboot database.");
-
let mut args = std::env::args();
args.next().expect("That's odd. How is there not even a first argument?");
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index a099d18..0633bc1 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -179,8 +179,8 @@
check_keystore_permission(KeystorePerm::report_off_body())
.context("In on_device_off_body.")?;
- DB.with(|db| db.borrow_mut().update_last_off_body(MonotonicRawTime::now()))
- .context("In on_device_off_body: Trying to update last off body time.")
+ DB.with(|db| db.borrow_mut().update_last_off_body(MonotonicRawTime::now()));
+ Ok(())
}
fn migrate_key_namespace(source: &KeyDescriptor, destination: &KeyDescriptor) -> Result<()> {
diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs
index 848707c..7a8b9be 100644
--- a/keystore2/src/super_key.rs
+++ b/keystore2/src/super_key.rs
@@ -992,7 +992,7 @@
for sid in &biometric.sids {
if let Some((auth_token_entry, _)) = db.find_auth_token_entry(|entry| {
entry.auth_token().userId == *sid || entry.auth_token().authenticatorId == *sid
- })? {
+ }) {
let res: Result<(Arc<SuperKey>, Arc<SuperKey>)> = (|| {
let slb = biometric.screen_lock_bound.decrypt(
db,