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
This commit is contained in:
Matthew Maurer 2021-05-06 21:58:45 -07:00
parent 4fb1911b8a
commit d7815caead
8 changed files with 222 additions and 227 deletions

View file

@ -121,7 +121,7 @@ impl AuthorizationManager {
// 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(())
}

View file

@ -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 @@ use android_hardware_security_keymint::aidl::android::hardware::security::keymin
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 @@ impl<T> DoGc<T> for Result<T> {
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 @@ impl FromSql for MonotonicRawTime {
/// 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 @@ pub struct PerBootDbKeepAlive(Connection);
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 @@ impl KeystoreDB {
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 @@ impl KeystoreDB {
)
.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 @@ impl KeystoreDB {
}
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 @@ impl KeystoreDB {
}
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 @@ impl KeystoreDB {
}
}
/// 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 @@ mod tests {
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 @@ mod tests {
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 @@ mod tests {
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 @@ mod tests {
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 @@ mod tests {
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 @@ mod tests {
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 @@ mod tests {
#[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 @@ mod tests {
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 @@ mod tests {
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 @@ mod tests {
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(())
}
}

View file

@ -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()
}
}

View file

@ -638,8 +638,7 @@ impl Enforcements {
} 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 @@ impl Enforcements {
})
}
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 @@ impl Enforcements {
/// 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 @@ impl Enforcements {
// 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 @@ impl Enforcements {
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()

View file

@ -61,8 +61,7 @@ pub fn create_thread_local_db() -> KeystoreDB {
.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 {

View file

@ -47,10 +47,6 @@ fn main() {
// 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?");

View file

@ -179,8 +179,8 @@ impl Maintenance {
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<()> {

View file

@ -992,7 +992,7 @@ impl SuperKeyManager {
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,