1 // Copyright 2020, 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 is the Keystore 2.0 database module. 16 //! The database module provides a connection to the backing SQLite store. 17 //! We have two databases one for persistent key blob storage and one for 18 //! items that have a per boot life cycle. 19 //! 20 //! ## Persistent database 21 //! The persistent database has tables for key blobs. They are organized 22 //! as follows: 23 //! The `keyentry` table is the primary table for key entries. It is 24 //! accompanied by two tables for blobs and parameters. 25 //! Each key entry occupies exactly one row in the `keyentry` table and 26 //! zero or more rows in the tables `blobentry` and `keyparameter`. 27 //! 28 //! ## Per boot database 29 //! The per boot database stores items with a per boot lifecycle. 30 //! Currently, there is only the `grant` table in this database. 31 //! Grants are references to a key that can be used to access a key by 32 //! clients that don't own that key. Grants can only be created by the 33 //! owner of a key. And only certain components can create grants. 34 //! This is governed by SEPolicy. 35 //! 36 //! ## Access control 37 //! Some database functions that load keys or create grants perform 38 //! access control. This is because in some cases access control 39 //! can only be performed after some information about the designated 40 //! key was loaded from the database. To decouple the permission checks 41 //! from the database module these functions take permission check 42 //! callbacks. 43 44 mod perboot; 45 pub(crate) mod utils; 46 mod versioning; 47 48 use crate::impl_metadata; // This is in db_utils.rs 49 use crate::key_parameter::{KeyParameter, Tag}; 50 use crate::metrics_store::log_rkp_error_stats; 51 use crate::permission::KeyPermSet; 52 use crate::utils::{get_current_time_in_milliseconds, watchdog as wd, AID_USER_OFFSET}; 53 use crate::{ 54 error::{Error as KsError, ErrorCode, ResponseCode}, 55 super_key::SuperKeyType, 56 }; 57 use crate::{gc::Gc, super_key::USER_SUPER_KEY}; 58 use anyhow::{anyhow, Context, Result}; 59 use std::{convert::TryFrom, convert::TryInto, ops::Deref, time::SystemTimeError}; 60 use utils as db_utils; 61 use utils::SqlField; 62 63 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ 64 HardwareAuthToken::HardwareAuthToken, 65 HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel, 66 }; 67 use android_system_keystore2::aidl::android::system::keystore2::{ 68 Domain::Domain, KeyDescriptor::KeyDescriptor, 69 }; 70 use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{ 71 AttestationPoolStatus::AttestationPoolStatus, 72 }; 73 use android_security_metrics::aidl::android::security::metrics::{ 74 StorageStats::StorageStats, 75 Storage::Storage as MetricsStorage, 76 RkpError::RkpError as MetricsRkpError, 77 }; 78 79 use keystore2_crypto::ZVec; 80 use lazy_static::lazy_static; 81 use log::error; 82 #[cfg(not(test))] 83 use rand::prelude::random; 84 use rusqlite::{ 85 params, 86 types::FromSql, 87 types::FromSqlResult, 88 types::ToSqlOutput, 89 types::{FromSqlError, Value, ValueRef}, 90 Connection, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS, 91 }; 92 93 use std::{ 94 collections::{HashMap, HashSet}, 95 path::Path, 96 sync::{Arc, Condvar, Mutex}, 97 time::{Duration, SystemTime}, 98 }; 99 100 #[cfg(test)] 101 use tests::random; 102 103 impl_metadata!( 104 /// A set of metadata for key entries. 105 #[derive(Debug, Default, Eq, PartialEq)] 106 pub struct KeyMetaData; 107 /// A metadata entry for key entries. 108 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] 109 pub enum KeyMetaEntry { 110 /// Date of the creation of the key entry. 111 CreationDate(DateTime) with accessor creation_date, 112 /// Expiration date for attestation keys. 113 AttestationExpirationDate(DateTime) with accessor attestation_expiration_date, 114 /// CBOR Blob that represents a COSE_Key and associated metadata needed for remote 115 /// provisioning 116 AttestationMacedPublicKey(Vec<u8>) with accessor attestation_maced_public_key, 117 /// Vector representing the raw public key so results from the server can be matched 118 /// to the right entry 119 AttestationRawPubKey(Vec<u8>) with accessor attestation_raw_pub_key, 120 /// SEC1 public key for ECDH encryption 121 Sec1PublicKey(Vec<u8>) with accessor sec1_public_key, 122 // --- ADD NEW META DATA FIELDS HERE --- 123 // For backwards compatibility add new entries only to 124 // end of this list and above this comment. 125 }; 126 ); 127 128 impl KeyMetaData { load_from_db(key_id: i64, tx: &Transaction) -> Result<Self>129 fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> { 130 let mut stmt = tx 131 .prepare( 132 "SELECT tag, data from persistent.keymetadata 133 WHERE keyentryid = ?;", 134 ) 135 .context("In KeyMetaData::load_from_db: prepare statement failed.")?; 136 137 let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default(); 138 139 let mut rows = 140 stmt.query(params![key_id]).context("In KeyMetaData::load_from_db: query failed.")?; 141 db_utils::with_rows_extract_all(&mut rows, |row| { 142 let db_tag: i64 = row.get(0).context("Failed to read tag.")?; 143 metadata.insert( 144 db_tag, 145 KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row)) 146 .context("Failed to read KeyMetaEntry.")?, 147 ); 148 Ok(()) 149 }) 150 .context("In KeyMetaData::load_from_db.")?; 151 152 Ok(Self { data: metadata }) 153 } 154 store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()>155 fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> { 156 let mut stmt = tx 157 .prepare( 158 "INSERT or REPLACE INTO persistent.keymetadata (keyentryid, tag, data) 159 VALUES (?, ?, ?);", 160 ) 161 .context("In KeyMetaData::store_in_db: Failed to prepare statement.")?; 162 163 let iter = self.data.iter(); 164 for (tag, entry) in iter { 165 stmt.insert(params![key_id, tag, entry,]).with_context(|| { 166 format!("In KeyMetaData::store_in_db: Failed to insert {:?}", entry) 167 })?; 168 } 169 Ok(()) 170 } 171 } 172 173 impl_metadata!( 174 /// A set of metadata for key blobs. 175 #[derive(Debug, Default, Eq, PartialEq)] 176 pub struct BlobMetaData; 177 /// A metadata entry for key blobs. 178 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] 179 pub enum BlobMetaEntry { 180 /// If present, indicates that the blob is encrypted with another key or a key derived 181 /// from a password. 182 EncryptedBy(EncryptedBy) with accessor encrypted_by, 183 /// If the blob is password encrypted this field is set to the 184 /// salt used for the key derivation. 185 Salt(Vec<u8>) with accessor salt, 186 /// If the blob is encrypted, this field is set to the initialization vector. 187 Iv(Vec<u8>) with accessor iv, 188 /// If the blob is encrypted, this field holds the AEAD TAG. 189 AeadTag(Vec<u8>) with accessor aead_tag, 190 /// The uuid of the owning KeyMint instance. 191 KmUuid(Uuid) with accessor km_uuid, 192 /// If the key is ECDH encrypted, this is the ephemeral public key 193 PublicKey(Vec<u8>) with accessor public_key, 194 /// If the key is encrypted with a MaxBootLevel key, this is the boot level 195 /// of that key 196 MaxBootLevel(i32) with accessor max_boot_level, 197 // --- ADD NEW META DATA FIELDS HERE --- 198 // For backwards compatibility add new entries only to 199 // end of this list and above this comment. 200 }; 201 ); 202 203 impl BlobMetaData { load_from_db(blob_id: i64, tx: &Transaction) -> Result<Self>204 fn load_from_db(blob_id: i64, tx: &Transaction) -> Result<Self> { 205 let mut stmt = tx 206 .prepare( 207 "SELECT tag, data from persistent.blobmetadata 208 WHERE blobentryid = ?;", 209 ) 210 .context("In BlobMetaData::load_from_db: prepare statement failed.")?; 211 212 let mut metadata: HashMap<i64, BlobMetaEntry> = Default::default(); 213 214 let mut rows = 215 stmt.query(params![blob_id]).context("In BlobMetaData::load_from_db: query failed.")?; 216 db_utils::with_rows_extract_all(&mut rows, |row| { 217 let db_tag: i64 = row.get(0).context("Failed to read tag.")?; 218 metadata.insert( 219 db_tag, 220 BlobMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row)) 221 .context("Failed to read BlobMetaEntry.")?, 222 ); 223 Ok(()) 224 }) 225 .context("In BlobMetaData::load_from_db.")?; 226 227 Ok(Self { data: metadata }) 228 } 229 store_in_db(&self, blob_id: i64, tx: &Transaction) -> Result<()>230 fn store_in_db(&self, blob_id: i64, tx: &Transaction) -> Result<()> { 231 let mut stmt = tx 232 .prepare( 233 "INSERT or REPLACE INTO persistent.blobmetadata (blobentryid, tag, data) 234 VALUES (?, ?, ?);", 235 ) 236 .context("In BlobMetaData::store_in_db: Failed to prepare statement.")?; 237 238 let iter = self.data.iter(); 239 for (tag, entry) in iter { 240 stmt.insert(params![blob_id, tag, entry,]).with_context(|| { 241 format!("In BlobMetaData::store_in_db: Failed to insert {:?}", entry) 242 })?; 243 } 244 Ok(()) 245 } 246 } 247 248 /// Indicates the type of the keyentry. 249 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] 250 pub enum KeyType { 251 /// This is a client key type. These keys are created or imported through the Keystore 2.0 252 /// AIDL interface android.system.keystore2. 253 Client, 254 /// This is a super key type. These keys are created by keystore itself and used to encrypt 255 /// other key blobs to provide LSKF binding. 256 Super, 257 /// This is an attestation key. These keys are created by the remote provisioning mechanism. 258 Attestation, 259 } 260 261 impl ToSql for KeyType { to_sql(&self) -> rusqlite::Result<ToSqlOutput>262 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 263 Ok(ToSqlOutput::Owned(Value::Integer(match self { 264 KeyType::Client => 0, 265 KeyType::Super => 1, 266 KeyType::Attestation => 2, 267 }))) 268 } 269 } 270 271 impl FromSql for KeyType { column_result(value: ValueRef) -> FromSqlResult<Self>272 fn column_result(value: ValueRef) -> FromSqlResult<Self> { 273 match i64::column_result(value)? { 274 0 => Ok(KeyType::Client), 275 1 => Ok(KeyType::Super), 276 2 => Ok(KeyType::Attestation), 277 v => Err(FromSqlError::OutOfRange(v)), 278 } 279 } 280 } 281 282 /// Uuid representation that can be stored in the database. 283 /// Right now it can only be initialized from SecurityLevel. 284 /// Once KeyMint provides a UUID type a corresponding From impl shall be added. 285 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] 286 pub struct Uuid([u8; 16]); 287 288 impl Deref for Uuid { 289 type Target = [u8; 16]; 290 deref(&self) -> &Self::Target291 fn deref(&self) -> &Self::Target { 292 &self.0 293 } 294 } 295 296 impl From<SecurityLevel> for Uuid { from(sec_level: SecurityLevel) -> Self297 fn from(sec_level: SecurityLevel) -> Self { 298 Self((sec_level.0 as u128).to_be_bytes()) 299 } 300 } 301 302 impl ToSql for Uuid { to_sql(&self) -> rusqlite::Result<ToSqlOutput>303 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 304 self.0.to_sql() 305 } 306 } 307 308 impl FromSql for Uuid { column_result(value: ValueRef<'_>) -> FromSqlResult<Self>309 fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> { 310 let blob = Vec::<u8>::column_result(value)?; 311 if blob.len() != 16 { 312 return Err(FromSqlError::OutOfRange(blob.len() as i64)); 313 } 314 let mut arr = [0u8; 16]; 315 arr.copy_from_slice(&blob); 316 Ok(Self(arr)) 317 } 318 } 319 320 /// Key entries that are not associated with any KeyMint instance, such as pure certificate 321 /// entries are associated with this UUID. 322 pub static KEYSTORE_UUID: Uuid = Uuid([ 323 0x41, 0xe3, 0xb9, 0xce, 0x27, 0x58, 0x4e, 0x91, 0xbc, 0xfd, 0xa5, 0x5d, 0x91, 0x85, 0xab, 0x11, 324 ]); 325 326 /// Indicates how the sensitive part of this key blob is encrypted. 327 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] 328 pub enum EncryptedBy { 329 /// The keyblob is encrypted by a user password. 330 /// In the database this variant is represented as NULL. 331 Password, 332 /// The keyblob is encrypted by another key with wrapped key id. 333 /// In the database this variant is represented as non NULL value 334 /// that is convertible to i64, typically NUMERIC. 335 KeyId(i64), 336 } 337 338 impl ToSql for EncryptedBy { to_sql(&self) -> rusqlite::Result<ToSqlOutput>339 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 340 match self { 341 Self::Password => Ok(ToSqlOutput::Owned(Value::Null)), 342 Self::KeyId(id) => id.to_sql(), 343 } 344 } 345 } 346 347 impl FromSql for EncryptedBy { column_result(value: ValueRef) -> FromSqlResult<Self>348 fn column_result(value: ValueRef) -> FromSqlResult<Self> { 349 match value { 350 ValueRef::Null => Ok(Self::Password), 351 _ => Ok(Self::KeyId(i64::column_result(value)?)), 352 } 353 } 354 } 355 356 /// A database representation of wall clock time. DateTime stores unix epoch time as 357 /// i64 in milliseconds. 358 #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] 359 pub struct DateTime(i64); 360 361 /// Error type returned when creating DateTime or converting it from and to 362 /// SystemTime. 363 #[derive(thiserror::Error, Debug)] 364 pub enum DateTimeError { 365 /// This is returned when SystemTime and Duration computations fail. 366 #[error(transparent)] 367 SystemTimeError(#[from] SystemTimeError), 368 369 /// This is returned when type conversions fail. 370 #[error(transparent)] 371 TypeConversion(#[from] std::num::TryFromIntError), 372 373 /// This is returned when checked time arithmetic failed. 374 #[error("Time arithmetic failed.")] 375 TimeArithmetic, 376 } 377 378 impl DateTime { 379 /// Constructs a new DateTime object denoting the current time. This may fail during 380 /// conversion to unix epoch time and during conversion to the internal i64 representation. now() -> Result<Self, DateTimeError>381 pub fn now() -> Result<Self, DateTimeError> { 382 Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?)) 383 } 384 385 /// Constructs a new DateTime object from milliseconds. from_millis_epoch(millis: i64) -> Self386 pub fn from_millis_epoch(millis: i64) -> Self { 387 Self(millis) 388 } 389 390 /// Returns unix epoch time in milliseconds. to_millis_epoch(&self) -> i64391 pub fn to_millis_epoch(&self) -> i64 { 392 self.0 393 } 394 395 /// Returns unix epoch time in seconds. to_secs_epoch(&self) -> i64396 pub fn to_secs_epoch(&self) -> i64 { 397 self.0 / 1000 398 } 399 } 400 401 impl ToSql for DateTime { to_sql(&self) -> rusqlite::Result<ToSqlOutput>402 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 403 Ok(ToSqlOutput::Owned(Value::Integer(self.0))) 404 } 405 } 406 407 impl FromSql for DateTime { column_result(value: ValueRef) -> FromSqlResult<Self>408 fn column_result(value: ValueRef) -> FromSqlResult<Self> { 409 Ok(Self(i64::column_result(value)?)) 410 } 411 } 412 413 impl TryInto<SystemTime> for DateTime { 414 type Error = DateTimeError; 415 try_into(self) -> Result<SystemTime, Self::Error>416 fn try_into(self) -> Result<SystemTime, Self::Error> { 417 // We want to construct a SystemTime representation equivalent to self, denoting 418 // a point in time THEN, but we cannot set the time directly. We can only construct 419 // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW, 420 // and between EPOCH and THEN. With this common reference we can construct the 421 // duration between NOW and THEN which we can add to our SystemTime representation 422 // of NOW to get a SystemTime representation of THEN. 423 // Durations can only be positive, thus the if statement below. 424 let now = SystemTime::now(); 425 let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?; 426 let then_epoch = Duration::from_millis(self.0.try_into()?); 427 Ok(if now_epoch > then_epoch { 428 // then = now - (now_epoch - then_epoch) 429 now_epoch 430 .checked_sub(then_epoch) 431 .and_then(|d| now.checked_sub(d)) 432 .ok_or(DateTimeError::TimeArithmetic)? 433 } else { 434 // then = now + (then_epoch - now_epoch) 435 then_epoch 436 .checked_sub(now_epoch) 437 .and_then(|d| now.checked_add(d)) 438 .ok_or(DateTimeError::TimeArithmetic)? 439 }) 440 } 441 } 442 443 impl TryFrom<SystemTime> for DateTime { 444 type Error = DateTimeError; 445 try_from(t: SystemTime) -> Result<Self, Self::Error>446 fn try_from(t: SystemTime) -> Result<Self, Self::Error> { 447 Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?)) 448 } 449 } 450 451 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] 452 enum KeyLifeCycle { 453 /// Existing keys have a key ID but are not fully populated yet. 454 /// This is a transient state. If Keystore finds any such keys when it starts up, it must move 455 /// them to Unreferenced for garbage collection. 456 Existing, 457 /// A live key is fully populated and usable by clients. 458 Live, 459 /// An unreferenced key is scheduled for garbage collection. 460 Unreferenced, 461 } 462 463 impl ToSql for KeyLifeCycle { to_sql(&self) -> rusqlite::Result<ToSqlOutput>464 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 465 match self { 466 Self::Existing => Ok(ToSqlOutput::Owned(Value::Integer(0))), 467 Self::Live => Ok(ToSqlOutput::Owned(Value::Integer(1))), 468 Self::Unreferenced => Ok(ToSqlOutput::Owned(Value::Integer(2))), 469 } 470 } 471 } 472 473 impl FromSql for KeyLifeCycle { column_result(value: ValueRef) -> FromSqlResult<Self>474 fn column_result(value: ValueRef) -> FromSqlResult<Self> { 475 match i64::column_result(value)? { 476 0 => Ok(KeyLifeCycle::Existing), 477 1 => Ok(KeyLifeCycle::Live), 478 2 => Ok(KeyLifeCycle::Unreferenced), 479 v => Err(FromSqlError::OutOfRange(v)), 480 } 481 } 482 } 483 484 /// Keys have a KeyMint blob component and optional public certificate and 485 /// certificate chain components. 486 /// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry` 487 /// which components shall be loaded from the database if present. 488 #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] 489 pub struct KeyEntryLoadBits(u32); 490 491 impl KeyEntryLoadBits { 492 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded. 493 pub const NONE: KeyEntryLoadBits = Self(0); 494 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded. 495 pub const KM: KeyEntryLoadBits = Self(1); 496 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded. 497 pub const PUBLIC: KeyEntryLoadBits = Self(2); 498 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded. 499 pub const BOTH: KeyEntryLoadBits = Self(3); 500 501 /// Returns true if this object indicates that the public components shall be loaded. load_public(&self) -> bool502 pub const fn load_public(&self) -> bool { 503 self.0 & Self::PUBLIC.0 != 0 504 } 505 506 /// Returns true if the object indicates that the KeyMint component shall be loaded. load_km(&self) -> bool507 pub const fn load_km(&self) -> bool { 508 self.0 & Self::KM.0 != 0 509 } 510 } 511 512 lazy_static! { 513 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new(); 514 } 515 516 struct KeyIdLockDb { 517 locked_keys: Mutex<HashSet<i64>>, 518 cond_var: Condvar, 519 } 520 521 /// A locked key. While a guard exists for a given key id, the same key cannot be loaded 522 /// from the database a second time. Most functions manipulating the key blob database 523 /// require a KeyIdGuard. 524 #[derive(Debug)] 525 pub struct KeyIdGuard(i64); 526 527 impl KeyIdLockDb { new() -> Self528 fn new() -> Self { 529 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() } 530 } 531 532 /// This function blocks until an exclusive lock for the given key entry id can 533 /// be acquired. It returns a guard object, that represents the lifecycle of the 534 /// acquired lock. get(&self, key_id: i64) -> KeyIdGuard535 pub fn get(&self, key_id: i64) -> KeyIdGuard { 536 let mut locked_keys = self.locked_keys.lock().unwrap(); 537 while locked_keys.contains(&key_id) { 538 locked_keys = self.cond_var.wait(locked_keys).unwrap(); 539 } 540 locked_keys.insert(key_id); 541 KeyIdGuard(key_id) 542 } 543 544 /// This function attempts to acquire an exclusive lock on a given key id. If the 545 /// given key id is already taken the function returns None immediately. If a lock 546 /// can be acquired this function returns a guard object, that represents the 547 /// lifecycle of the acquired lock. try_get(&self, key_id: i64) -> Option<KeyIdGuard>548 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> { 549 let mut locked_keys = self.locked_keys.lock().unwrap(); 550 if locked_keys.insert(key_id) { 551 Some(KeyIdGuard(key_id)) 552 } else { 553 None 554 } 555 } 556 } 557 558 impl KeyIdGuard { 559 /// Get the numeric key id of the locked key. id(&self) -> i64560 pub fn id(&self) -> i64 { 561 self.0 562 } 563 } 564 565 impl Drop for KeyIdGuard { drop(&mut self)566 fn drop(&mut self) { 567 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap(); 568 locked_keys.remove(&self.0); 569 drop(locked_keys); 570 KEY_ID_LOCK.cond_var.notify_all(); 571 } 572 } 573 574 /// This type represents a certificate and certificate chain entry for a key. 575 #[derive(Debug, Default)] 576 pub struct CertificateInfo { 577 cert: Option<Vec<u8>>, 578 cert_chain: Option<Vec<u8>>, 579 } 580 581 impl CertificateInfo { 582 /// Constructs a new CertificateInfo object from `cert` and `cert_chain` new(cert: Option<Vec<u8>>, cert_chain: Option<Vec<u8>>) -> Self583 pub fn new(cert: Option<Vec<u8>>, cert_chain: Option<Vec<u8>>) -> Self { 584 Self { cert, cert_chain } 585 } 586 587 /// Take the cert take_cert(&mut self) -> Option<Vec<u8>>588 pub fn take_cert(&mut self) -> Option<Vec<u8>> { 589 self.cert.take() 590 } 591 592 /// Take the cert chain take_cert_chain(&mut self) -> Option<Vec<u8>>593 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> { 594 self.cert_chain.take() 595 } 596 } 597 598 /// This type represents a certificate chain with a private key corresponding to the leaf 599 /// certificate. TODO(jbires): This will be used in a follow-on CL, for now it's used in the tests. 600 pub struct CertificateChain { 601 /// A KM key blob 602 pub private_key: ZVec, 603 /// A batch cert for private_key 604 pub batch_cert: Vec<u8>, 605 /// A full certificate chain from root signing authority to private_key, including batch_cert 606 /// for convenience. 607 pub cert_chain: Vec<u8>, 608 } 609 610 /// This type represents a Keystore 2.0 key entry. 611 /// An entry has a unique `id` by which it can be found in the database. 612 /// It has a security level field, key parameters, and three optional fields 613 /// for the KeyMint blob, public certificate and a public certificate chain. 614 #[derive(Debug, Default, Eq, PartialEq)] 615 pub struct KeyEntry { 616 id: i64, 617 key_blob_info: Option<(Vec<u8>, BlobMetaData)>, 618 cert: Option<Vec<u8>>, 619 cert_chain: Option<Vec<u8>>, 620 km_uuid: Uuid, 621 parameters: Vec<KeyParameter>, 622 metadata: KeyMetaData, 623 pure_cert: bool, 624 } 625 626 impl KeyEntry { 627 /// Returns the unique id of the Key entry. id(&self) -> i64628 pub fn id(&self) -> i64 { 629 self.id 630 } 631 /// Exposes the optional KeyMint blob. key_blob_info(&self) -> &Option<(Vec<u8>, BlobMetaData)>632 pub fn key_blob_info(&self) -> &Option<(Vec<u8>, BlobMetaData)> { 633 &self.key_blob_info 634 } 635 /// Extracts the Optional KeyMint blob including its metadata. take_key_blob_info(&mut self) -> Option<(Vec<u8>, BlobMetaData)>636 pub fn take_key_blob_info(&mut self) -> Option<(Vec<u8>, BlobMetaData)> { 637 self.key_blob_info.take() 638 } 639 /// Exposes the optional public certificate. cert(&self) -> &Option<Vec<u8>>640 pub fn cert(&self) -> &Option<Vec<u8>> { 641 &self.cert 642 } 643 /// Extracts the optional public certificate. take_cert(&mut self) -> Option<Vec<u8>>644 pub fn take_cert(&mut self) -> Option<Vec<u8>> { 645 self.cert.take() 646 } 647 /// Exposes the optional public certificate chain. cert_chain(&self) -> &Option<Vec<u8>>648 pub fn cert_chain(&self) -> &Option<Vec<u8>> { 649 &self.cert_chain 650 } 651 /// Extracts the optional public certificate_chain. take_cert_chain(&mut self) -> Option<Vec<u8>>652 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> { 653 self.cert_chain.take() 654 } 655 /// Returns the uuid of the owning KeyMint instance. km_uuid(&self) -> &Uuid656 pub fn km_uuid(&self) -> &Uuid { 657 &self.km_uuid 658 } 659 /// Exposes the key parameters of this key entry. key_parameters(&self) -> &Vec<KeyParameter>660 pub fn key_parameters(&self) -> &Vec<KeyParameter> { 661 &self.parameters 662 } 663 /// Consumes this key entry and extracts the keyparameters from it. into_key_parameters(self) -> Vec<KeyParameter>664 pub fn into_key_parameters(self) -> Vec<KeyParameter> { 665 self.parameters 666 } 667 /// Exposes the key metadata of this key entry. metadata(&self) -> &KeyMetaData668 pub fn metadata(&self) -> &KeyMetaData { 669 &self.metadata 670 } 671 /// This returns true if the entry is a pure certificate entry with no 672 /// private key component. pure_cert(&self) -> bool673 pub fn pure_cert(&self) -> bool { 674 self.pure_cert 675 } 676 /// Consumes this key entry and extracts the keyparameters and metadata from it. into_key_parameters_and_metadata(self) -> (Vec<KeyParameter>, KeyMetaData)677 pub fn into_key_parameters_and_metadata(self) -> (Vec<KeyParameter>, KeyMetaData) { 678 (self.parameters, self.metadata) 679 } 680 } 681 682 /// Indicates the sub component of a key entry for persistent storage. 683 #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] 684 pub struct SubComponentType(u32); 685 impl SubComponentType { 686 /// Persistent identifier for a key blob. 687 pub const KEY_BLOB: SubComponentType = Self(0); 688 /// Persistent identifier for a certificate blob. 689 pub const CERT: SubComponentType = Self(1); 690 /// Persistent identifier for a certificate chain blob. 691 pub const CERT_CHAIN: SubComponentType = Self(2); 692 } 693 694 impl ToSql for SubComponentType { to_sql(&self) -> rusqlite::Result<ToSqlOutput>695 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 696 self.0.to_sql() 697 } 698 } 699 700 impl FromSql for SubComponentType { column_result(value: ValueRef) -> FromSqlResult<Self>701 fn column_result(value: ValueRef) -> FromSqlResult<Self> { 702 Ok(Self(u32::column_result(value)?)) 703 } 704 } 705 706 /// This trait is private to the database module. It is used to convey whether or not the garbage 707 /// collector shall be invoked after a database access. All closures passed to 708 /// `KeystoreDB::with_transaction` return a tuple (bool, T) where the bool indicates if the 709 /// gc needs to be triggered. This convenience function allows to turn any anyhow::Result<T> 710 /// into anyhow::Result<(bool, T)> by simply appending one of `.do_gc(bool)`, `.no_gc()`, or 711 /// `.need_gc()`. 712 trait DoGc<T> { do_gc(self, need_gc: bool) -> Result<(bool, T)>713 fn do_gc(self, need_gc: bool) -> Result<(bool, T)>; 714 no_gc(self) -> Result<(bool, T)>715 fn no_gc(self) -> Result<(bool, T)>; 716 need_gc(self) -> Result<(bool, T)>717 fn need_gc(self) -> Result<(bool, T)>; 718 } 719 720 impl<T> DoGc<T> for Result<T> { do_gc(self, need_gc: bool) -> Result<(bool, T)>721 fn do_gc(self, need_gc: bool) -> Result<(bool, T)> { 722 self.map(|r| (need_gc, r)) 723 } 724 no_gc(self) -> Result<(bool, T)>725 fn no_gc(self) -> Result<(bool, T)> { 726 self.do_gc(false) 727 } 728 need_gc(self) -> Result<(bool, T)>729 fn need_gc(self) -> Result<(bool, T)> { 730 self.do_gc(true) 731 } 732 } 733 734 /// KeystoreDB wraps a connection to an SQLite database and tracks its 735 /// ownership. It also implements all of Keystore 2.0's database functionality. 736 pub struct KeystoreDB { 737 conn: Connection, 738 gc: Option<Arc<Gc>>, 739 perboot: Arc<perboot::PerbootDB>, 740 } 741 742 /// Database representation of the monotonic time retrieved from the system call clock_gettime with 743 /// CLOCK_MONOTONIC_RAW. Stores monotonic time as i64 in milliseconds. 744 #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] 745 pub struct MonotonicRawTime(i64); 746 747 impl MonotonicRawTime { 748 /// Constructs a new MonotonicRawTime now() -> Self749 pub fn now() -> Self { 750 Self(get_current_time_in_milliseconds()) 751 } 752 753 /// Returns the value of MonotonicRawTime in milliseconds as i64 milliseconds(&self) -> i64754 pub fn milliseconds(&self) -> i64 { 755 self.0 756 } 757 758 /// Returns the integer value of MonotonicRawTime as i64 seconds(&self) -> i64759 pub fn seconds(&self) -> i64 { 760 self.0 / 1000 761 } 762 763 /// Like i64::checked_sub. checked_sub(&self, other: &Self) -> Option<Self>764 pub fn checked_sub(&self, other: &Self) -> Option<Self> { 765 self.0.checked_sub(other.0).map(Self) 766 } 767 } 768 769 impl ToSql for MonotonicRawTime { to_sql(&self) -> rusqlite::Result<ToSqlOutput>770 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 771 Ok(ToSqlOutput::Owned(Value::Integer(self.0))) 772 } 773 } 774 775 impl FromSql for MonotonicRawTime { column_result(value: ValueRef) -> FromSqlResult<Self>776 fn column_result(value: ValueRef) -> FromSqlResult<Self> { 777 Ok(Self(i64::column_result(value)?)) 778 } 779 } 780 781 /// This struct encapsulates the information to be stored in the database about the auth tokens 782 /// received by keystore. 783 #[derive(Clone)] 784 pub struct AuthTokenEntry { 785 auth_token: HardwareAuthToken, 786 // Time received in milliseconds 787 time_received: MonotonicRawTime, 788 } 789 790 impl AuthTokenEntry { new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self791 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self { 792 AuthTokenEntry { auth_token, time_received } 793 } 794 795 /// Checks if this auth token satisfies the given authentication information. satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool796 pub fn satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool { 797 user_secure_ids.iter().any(|&sid| { 798 (sid == self.auth_token.userId || sid == self.auth_token.authenticatorId) 799 && (((auth_type.0 as i32) & (self.auth_token.authenticatorType.0 as i32)) != 0) 800 }) 801 } 802 803 /// Returns the auth token wrapped by the AuthTokenEntry auth_token(&self) -> &HardwareAuthToken804 pub fn auth_token(&self) -> &HardwareAuthToken { 805 &self.auth_token 806 } 807 808 /// Returns the auth token wrapped by the AuthTokenEntry take_auth_token(self) -> HardwareAuthToken809 pub fn take_auth_token(self) -> HardwareAuthToken { 810 self.auth_token 811 } 812 813 /// Returns the time that this auth token was received. time_received(&self) -> MonotonicRawTime814 pub fn time_received(&self) -> MonotonicRawTime { 815 self.time_received 816 } 817 818 /// Returns the challenge value of the auth token. challenge(&self) -> i64819 pub fn challenge(&self) -> i64 { 820 self.auth_token.challenge 821 } 822 } 823 824 /// Shared in-memory databases get destroyed as soon as the last connection to them gets closed. 825 /// This object does not allow access to the database connection. But it keeps a database 826 /// connection alive in order to keep the in memory per boot database alive. 827 pub struct PerBootDbKeepAlive(Connection); 828 829 impl KeystoreDB { 830 const UNASSIGNED_KEY_ID: i64 = -1i64; 831 const CURRENT_DB_VERSION: u32 = 1; 832 const UPGRADERS: &'static [fn(&Transaction) -> Result<u32>] = &[Self::from_0_to_1]; 833 834 /// Name of the file that holds the cross-boot persistent database. 835 pub const PERSISTENT_DB_FILENAME: &'static str = &"persistent.sqlite"; 836 837 /// This will create a new database connection connecting the two 838 /// files persistent.sqlite and perboot.sqlite in the given directory. 839 /// It also attempts to initialize all of the tables. 840 /// KeystoreDB cannot be used by multiple threads. 841 /// Each thread should open their own connection using `thread_local!`. new(db_root: &Path, gc: Option<Arc<Gc>>) -> Result<Self>842 pub fn new(db_root: &Path, gc: Option<Arc<Gc>>) -> Result<Self> { 843 let _wp = wd::watch_millis("KeystoreDB::new", 500); 844 845 let persistent_path = Self::make_persistent_path(&db_root)?; 846 let conn = Self::make_connection(&persistent_path)?; 847 848 let mut db = Self { conn, gc, perboot: perboot::PERBOOT_DB.clone() }; 849 db.with_transaction(TransactionBehavior::Immediate, |tx| { 850 versioning::upgrade_database(tx, Self::CURRENT_DB_VERSION, Self::UPGRADERS) 851 .context("In KeystoreDB::new: trying to upgrade database.")?; 852 Self::init_tables(tx).context("Trying to initialize tables.").no_gc() 853 })?; 854 Ok(db) 855 } 856 857 // This upgrade function deletes all MAX_BOOT_LEVEL keys, that were generated before 858 // cryptographic binding to the boot level keys was implemented. from_0_to_1(tx: &Transaction) -> Result<u32>859 fn from_0_to_1(tx: &Transaction) -> Result<u32> { 860 tx.execute( 861 "UPDATE persistent.keyentry SET state = ? 862 WHERE 863 id IN (SELECT keyentryid FROM persistent.keyparameter WHERE tag = ?) 864 AND 865 id NOT IN ( 866 SELECT keyentryid FROM persistent.blobentry 867 WHERE id IN ( 868 SELECT blobentryid FROM persistent.blobmetadata WHERE tag = ? 869 ) 870 );", 871 params![KeyLifeCycle::Unreferenced, Tag::MAX_BOOT_LEVEL.0, BlobMetaData::MaxBootLevel], 872 ) 873 .context("In from_0_to_1: Failed to delete logical boot level keys.")?; 874 Ok(1) 875 } 876 init_tables(tx: &Transaction) -> Result<()>877 fn init_tables(tx: &Transaction) -> Result<()> { 878 tx.execute( 879 "CREATE TABLE IF NOT EXISTS persistent.keyentry ( 880 id INTEGER UNIQUE, 881 key_type INTEGER, 882 domain INTEGER, 883 namespace INTEGER, 884 alias BLOB, 885 state INTEGER, 886 km_uuid BLOB);", 887 NO_PARAMS, 888 ) 889 .context("Failed to initialize \"keyentry\" table.")?; 890 891 tx.execute( 892 "CREATE INDEX IF NOT EXISTS persistent.keyentry_id_index 893 ON keyentry(id);", 894 NO_PARAMS, 895 ) 896 .context("Failed to create index keyentry_id_index.")?; 897 898 tx.execute( 899 "CREATE INDEX IF NOT EXISTS persistent.keyentry_domain_namespace_index 900 ON keyentry(domain, namespace, alias);", 901 NO_PARAMS, 902 ) 903 .context("Failed to create index keyentry_domain_namespace_index.")?; 904 905 tx.execute( 906 "CREATE TABLE IF NOT EXISTS persistent.blobentry ( 907 id INTEGER PRIMARY KEY, 908 subcomponent_type INTEGER, 909 keyentryid INTEGER, 910 blob BLOB);", 911 NO_PARAMS, 912 ) 913 .context("Failed to initialize \"blobentry\" table.")?; 914 915 tx.execute( 916 "CREATE INDEX IF NOT EXISTS persistent.blobentry_keyentryid_index 917 ON blobentry(keyentryid);", 918 NO_PARAMS, 919 ) 920 .context("Failed to create index blobentry_keyentryid_index.")?; 921 922 tx.execute( 923 "CREATE TABLE IF NOT EXISTS persistent.blobmetadata ( 924 id INTEGER PRIMARY KEY, 925 blobentryid INTEGER, 926 tag INTEGER, 927 data ANY, 928 UNIQUE (blobentryid, tag));", 929 NO_PARAMS, 930 ) 931 .context("Failed to initialize \"blobmetadata\" table.")?; 932 933 tx.execute( 934 "CREATE INDEX IF NOT EXISTS persistent.blobmetadata_blobentryid_index 935 ON blobmetadata(blobentryid);", 936 NO_PARAMS, 937 ) 938 .context("Failed to create index blobmetadata_blobentryid_index.")?; 939 940 tx.execute( 941 "CREATE TABLE IF NOT EXISTS persistent.keyparameter ( 942 keyentryid INTEGER, 943 tag INTEGER, 944 data ANY, 945 security_level INTEGER);", 946 NO_PARAMS, 947 ) 948 .context("Failed to initialize \"keyparameter\" table.")?; 949 950 tx.execute( 951 "CREATE INDEX IF NOT EXISTS persistent.keyparameter_keyentryid_index 952 ON keyparameter(keyentryid);", 953 NO_PARAMS, 954 ) 955 .context("Failed to create index keyparameter_keyentryid_index.")?; 956 957 tx.execute( 958 "CREATE TABLE IF NOT EXISTS persistent.keymetadata ( 959 keyentryid INTEGER, 960 tag INTEGER, 961 data ANY, 962 UNIQUE (keyentryid, tag));", 963 NO_PARAMS, 964 ) 965 .context("Failed to initialize \"keymetadata\" table.")?; 966 967 tx.execute( 968 "CREATE INDEX IF NOT EXISTS persistent.keymetadata_keyentryid_index 969 ON keymetadata(keyentryid);", 970 NO_PARAMS, 971 ) 972 .context("Failed to create index keymetadata_keyentryid_index.")?; 973 974 tx.execute( 975 "CREATE TABLE IF NOT EXISTS persistent.grant ( 976 id INTEGER UNIQUE, 977 grantee INTEGER, 978 keyentryid INTEGER, 979 access_vector INTEGER);", 980 NO_PARAMS, 981 ) 982 .context("Failed to initialize \"grant\" table.")?; 983 984 Ok(()) 985 } 986 make_persistent_path(db_root: &Path) -> Result<String>987 fn make_persistent_path(db_root: &Path) -> Result<String> { 988 // Build the path to the sqlite file. 989 let mut persistent_path = db_root.to_path_buf(); 990 persistent_path.push(Self::PERSISTENT_DB_FILENAME); 991 992 // Now convert them to strings prefixed with "file:" 993 let mut persistent_path_str = "file:".to_owned(); 994 persistent_path_str.push_str(&persistent_path.to_string_lossy()); 995 996 Ok(persistent_path_str) 997 } 998 make_connection(persistent_file: &str) -> Result<Connection>999 fn make_connection(persistent_file: &str) -> Result<Connection> { 1000 let conn = 1001 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?; 1002 1003 loop { 1004 if let Err(e) = conn 1005 .execute("ATTACH DATABASE ? as persistent;", params![persistent_file]) 1006 .context("Failed to attach database persistent.") 1007 { 1008 if Self::is_locked_error(&e) { 1009 std::thread::sleep(std::time::Duration::from_micros(500)); 1010 continue; 1011 } else { 1012 return Err(e); 1013 } 1014 } 1015 break; 1016 } 1017 1018 // Drop the cache size from default (2M) to 0.5M 1019 conn.execute("PRAGMA persistent.cache_size = -500;", params![]) 1020 .context("Failed to decrease cache size for persistent db")?; 1021 1022 Ok(conn) 1023 } 1024 do_table_size_query( &mut self, storage_type: MetricsStorage, query: &str, params: &[&str], ) -> Result<StorageStats>1025 fn do_table_size_query( 1026 &mut self, 1027 storage_type: MetricsStorage, 1028 query: &str, 1029 params: &[&str], 1030 ) -> Result<StorageStats> { 1031 let (total, unused) = self.with_transaction(TransactionBehavior::Deferred, |tx| { 1032 tx.query_row(query, params, |row| Ok((row.get(0)?, row.get(1)?))) 1033 .with_context(|| { 1034 format!("get_storage_stat: Error size of storage type {}", storage_type.0) 1035 }) 1036 .no_gc() 1037 })?; 1038 Ok(StorageStats { storage_type, size: total, unused_size: unused }) 1039 } 1040 get_total_size(&mut self) -> Result<StorageStats>1041 fn get_total_size(&mut self) -> Result<StorageStats> { 1042 self.do_table_size_query( 1043 MetricsStorage::DATABASE, 1044 "SELECT page_count * page_size, freelist_count * page_size 1045 FROM pragma_page_count('persistent'), 1046 pragma_page_size('persistent'), 1047 persistent.pragma_freelist_count();", 1048 &[], 1049 ) 1050 } 1051 get_table_size( &mut self, storage_type: MetricsStorage, schema: &str, table: &str, ) -> Result<StorageStats>1052 fn get_table_size( 1053 &mut self, 1054 storage_type: MetricsStorage, 1055 schema: &str, 1056 table: &str, 1057 ) -> Result<StorageStats> { 1058 self.do_table_size_query( 1059 storage_type, 1060 "SELECT pgsize,unused FROM dbstat(?1) 1061 WHERE name=?2 AND aggregate=TRUE;", 1062 &[schema, table], 1063 ) 1064 } 1065 1066 /// Fetches a storage statisitics atom for a given storage type. For storage 1067 /// types that map to a table, information about the table's storage is 1068 /// returned. Requests for storage types that are not DB tables return None. get_storage_stat(&mut self, storage_type: MetricsStorage) -> Result<StorageStats>1069 pub fn get_storage_stat(&mut self, storage_type: MetricsStorage) -> Result<StorageStats> { 1070 let _wp = wd::watch_millis("KeystoreDB::get_storage_stat", 500); 1071 1072 match storage_type { 1073 MetricsStorage::DATABASE => self.get_total_size(), 1074 MetricsStorage::KEY_ENTRY => { 1075 self.get_table_size(storage_type, "persistent", "keyentry") 1076 } 1077 MetricsStorage::KEY_ENTRY_ID_INDEX => { 1078 self.get_table_size(storage_type, "persistent", "keyentry_id_index") 1079 } 1080 MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX => { 1081 self.get_table_size(storage_type, "persistent", "keyentry_domain_namespace_index") 1082 } 1083 MetricsStorage::BLOB_ENTRY => { 1084 self.get_table_size(storage_type, "persistent", "blobentry") 1085 } 1086 MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX => { 1087 self.get_table_size(storage_type, "persistent", "blobentry_keyentryid_index") 1088 } 1089 MetricsStorage::KEY_PARAMETER => { 1090 self.get_table_size(storage_type, "persistent", "keyparameter") 1091 } 1092 MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX => { 1093 self.get_table_size(storage_type, "persistent", "keyparameter_keyentryid_index") 1094 } 1095 MetricsStorage::KEY_METADATA => { 1096 self.get_table_size(storage_type, "persistent", "keymetadata") 1097 } 1098 MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX => { 1099 self.get_table_size(storage_type, "persistent", "keymetadata_keyentryid_index") 1100 } 1101 MetricsStorage::GRANT => self.get_table_size(storage_type, "persistent", "grant"), 1102 MetricsStorage::AUTH_TOKEN => { 1103 // Since the table is actually a BTreeMap now, unused_size is not meaningfully 1104 // reportable 1105 // Size provided is only an approximation 1106 Ok(StorageStats { 1107 storage_type, 1108 size: (self.perboot.auth_tokens_len() * std::mem::size_of::<AuthTokenEntry>()) 1109 as i32, 1110 unused_size: 0, 1111 }) 1112 } 1113 MetricsStorage::BLOB_METADATA => { 1114 self.get_table_size(storage_type, "persistent", "blobmetadata") 1115 } 1116 MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX => { 1117 self.get_table_size(storage_type, "persistent", "blobmetadata_blobentryid_index") 1118 } 1119 _ => Err(anyhow::Error::msg(format!("Unsupported storage type: {}", storage_type.0))), 1120 } 1121 } 1122 1123 /// This function is intended to be used by the garbage collector. 1124 /// It deletes the blobs given by `blob_ids_to_delete`. It then tries to find up to `max_blobs` 1125 /// superseded key blobs that might need special handling by the garbage collector. 1126 /// If no further superseded blobs can be found it deletes all other superseded blobs that don't 1127 /// need special handling and returns None. handle_next_superseded_blobs( &mut self, blob_ids_to_delete: &[i64], max_blobs: usize, ) -> Result<Vec<(i64, Vec<u8>, BlobMetaData)>>1128 pub fn handle_next_superseded_blobs( 1129 &mut self, 1130 blob_ids_to_delete: &[i64], 1131 max_blobs: usize, 1132 ) -> Result<Vec<(i64, Vec<u8>, BlobMetaData)>> { 1133 let _wp = wd::watch_millis("KeystoreDB::handle_next_superseded_blob", 500); 1134 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1135 // Delete the given blobs. 1136 for blob_id in blob_ids_to_delete { 1137 tx.execute( 1138 "DELETE FROM persistent.blobmetadata WHERE blobentryid = ?;", 1139 params![blob_id], 1140 ) 1141 .context("Trying to delete blob metadata.")?; 1142 tx.execute("DELETE FROM persistent.blobentry WHERE id = ?;", params![blob_id]) 1143 .context("Trying to blob.")?; 1144 } 1145 1146 Self::cleanup_unreferenced(tx).context("Trying to cleanup unreferenced.")?; 1147 1148 // Find up to max_blobx more superseded key blobs, load their metadata and return it. 1149 let result: Vec<(i64, Vec<u8>)> = { 1150 let mut stmt = tx 1151 .prepare( 1152 "SELECT id, blob FROM persistent.blobentry 1153 WHERE subcomponent_type = ? 1154 AND ( 1155 id NOT IN ( 1156 SELECT MAX(id) FROM persistent.blobentry 1157 WHERE subcomponent_type = ? 1158 GROUP BY keyentryid, subcomponent_type 1159 ) 1160 OR keyentryid NOT IN (SELECT id FROM persistent.keyentry) 1161 ) LIMIT ?;", 1162 ) 1163 .context("Trying to prepare query for superseded blobs.")?; 1164 1165 let rows = stmt 1166 .query_map( 1167 params![ 1168 SubComponentType::KEY_BLOB, 1169 SubComponentType::KEY_BLOB, 1170 max_blobs as i64, 1171 ], 1172 |row| Ok((row.get(0)?, row.get(1)?)), 1173 ) 1174 .context("Trying to query superseded blob.")?; 1175 1176 rows.collect::<Result<Vec<(i64, Vec<u8>)>, rusqlite::Error>>() 1177 .context("Trying to extract superseded blobs.")? 1178 }; 1179 1180 let result = result 1181 .into_iter() 1182 .map(|(blob_id, blob)| { 1183 Ok((blob_id, blob, BlobMetaData::load_from_db(blob_id, tx)?)) 1184 }) 1185 .collect::<Result<Vec<(i64, Vec<u8>, BlobMetaData)>>>() 1186 .context("Trying to load blob metadata.")?; 1187 if !result.is_empty() { 1188 return Ok(result).no_gc(); 1189 } 1190 1191 // We did not find any superseded key blob, so let's remove other superseded blob in 1192 // one transaction. 1193 tx.execute( 1194 "DELETE FROM persistent.blobentry 1195 WHERE NOT subcomponent_type = ? 1196 AND ( 1197 id NOT IN ( 1198 SELECT MAX(id) FROM persistent.blobentry 1199 WHERE NOT subcomponent_type = ? 1200 GROUP BY keyentryid, subcomponent_type 1201 ) OR keyentryid NOT IN (SELECT id FROM persistent.keyentry) 1202 );", 1203 params![SubComponentType::KEY_BLOB, SubComponentType::KEY_BLOB], 1204 ) 1205 .context("Trying to purge superseded blobs.")?; 1206 1207 Ok(vec![]).no_gc() 1208 }) 1209 .context("In handle_next_superseded_blobs.") 1210 } 1211 1212 /// This maintenance function should be called only once before the database is used for the 1213 /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state. 1214 /// The function transitions all key entries from Existing to Unreferenced unconditionally and 1215 /// returns the number of rows affected. If this returns a value greater than 0, it means that 1216 /// Keystore crashed at some point during key generation. Callers may want to log such 1217 /// occurrences. 1218 /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made 1219 /// it to `KeyLifeCycle::Live` may have grants. cleanup_leftovers(&mut self) -> Result<usize>1220 pub fn cleanup_leftovers(&mut self) -> Result<usize> { 1221 let _wp = wd::watch_millis("KeystoreDB::cleanup_leftovers", 500); 1222 1223 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1224 tx.execute( 1225 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;", 1226 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing], 1227 ) 1228 .context("Failed to execute query.") 1229 .need_gc() 1230 }) 1231 .context("In cleanup_leftovers.") 1232 } 1233 1234 /// Checks if a key exists with given key type and key descriptor properties. key_exists( &mut self, domain: Domain, nspace: i64, alias: &str, key_type: KeyType, ) -> Result<bool>1235 pub fn key_exists( 1236 &mut self, 1237 domain: Domain, 1238 nspace: i64, 1239 alias: &str, 1240 key_type: KeyType, 1241 ) -> Result<bool> { 1242 let _wp = wd::watch_millis("KeystoreDB::key_exists", 500); 1243 1244 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1245 let key_descriptor = 1246 KeyDescriptor { domain, nspace, alias: Some(alias.to_string()), blob: None }; 1247 let result = Self::load_key_entry_id(&tx, &key_descriptor, key_type); 1248 match result { 1249 Ok(_) => Ok(true), 1250 Err(error) => match error.root_cause().downcast_ref::<KsError>() { 1251 Some(KsError::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(false), 1252 _ => Err(error).context("In key_exists: Failed to find if the key exists."), 1253 }, 1254 } 1255 .no_gc() 1256 }) 1257 .context("In key_exists.") 1258 } 1259 1260 /// Stores a super key in the database. store_super_key( &mut self, user_id: u32, key_type: &SuperKeyType, blob: &[u8], blob_metadata: &BlobMetaData, key_metadata: &KeyMetaData, ) -> Result<KeyEntry>1261 pub fn store_super_key( 1262 &mut self, 1263 user_id: u32, 1264 key_type: &SuperKeyType, 1265 blob: &[u8], 1266 blob_metadata: &BlobMetaData, 1267 key_metadata: &KeyMetaData, 1268 ) -> Result<KeyEntry> { 1269 let _wp = wd::watch_millis("KeystoreDB::store_super_key", 500); 1270 1271 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1272 let key_id = Self::insert_with_retry(|id| { 1273 tx.execute( 1274 "INSERT into persistent.keyentry 1275 (id, key_type, domain, namespace, alias, state, km_uuid) 1276 VALUES(?, ?, ?, ?, ?, ?, ?);", 1277 params![ 1278 id, 1279 KeyType::Super, 1280 Domain::APP.0, 1281 user_id as i64, 1282 key_type.alias, 1283 KeyLifeCycle::Live, 1284 &KEYSTORE_UUID, 1285 ], 1286 ) 1287 }) 1288 .context("Failed to insert into keyentry table.")?; 1289 1290 key_metadata.store_in_db(key_id, tx).context("KeyMetaData::store_in_db failed")?; 1291 1292 Self::set_blob_internal( 1293 &tx, 1294 key_id, 1295 SubComponentType::KEY_BLOB, 1296 Some(blob), 1297 Some(blob_metadata), 1298 ) 1299 .context("Failed to store key blob.")?; 1300 1301 Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id) 1302 .context("Trying to load key components.") 1303 .no_gc() 1304 }) 1305 .context("In store_super_key.") 1306 } 1307 1308 /// Loads super key of a given user, if exists load_super_key( &mut self, key_type: &SuperKeyType, user_id: u32, ) -> Result<Option<(KeyIdGuard, KeyEntry)>>1309 pub fn load_super_key( 1310 &mut self, 1311 key_type: &SuperKeyType, 1312 user_id: u32, 1313 ) -> Result<Option<(KeyIdGuard, KeyEntry)>> { 1314 let _wp = wd::watch_millis("KeystoreDB::load_super_key", 500); 1315 1316 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1317 let key_descriptor = KeyDescriptor { 1318 domain: Domain::APP, 1319 nspace: user_id as i64, 1320 alias: Some(key_type.alias.into()), 1321 blob: None, 1322 }; 1323 let id = Self::load_key_entry_id(&tx, &key_descriptor, KeyType::Super); 1324 match id { 1325 Ok(id) => { 1326 let key_entry = Self::load_key_components(&tx, KeyEntryLoadBits::KM, id) 1327 .context("In load_super_key. Failed to load key entry.")?; 1328 Ok(Some((KEY_ID_LOCK.get(id), key_entry))) 1329 } 1330 Err(error) => match error.root_cause().downcast_ref::<KsError>() { 1331 Some(KsError::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None), 1332 _ => Err(error).context("In load_super_key."), 1333 }, 1334 } 1335 .no_gc() 1336 }) 1337 .context("In load_super_key.") 1338 } 1339 1340 /// Atomically loads a key entry and associated metadata or creates it using the 1341 /// callback create_new_key callback. The callback is called during a database 1342 /// transaction. This means that implementers should be mindful about using 1343 /// blocking operations such as IPC or grabbing mutexes. get_or_create_key_with<F>( &mut self, domain: Domain, namespace: i64, alias: &str, km_uuid: Uuid, create_new_key: F, ) -> Result<(KeyIdGuard, KeyEntry)> where F: Fn() -> Result<(Vec<u8>, BlobMetaData)>,1344 pub fn get_or_create_key_with<F>( 1345 &mut self, 1346 domain: Domain, 1347 namespace: i64, 1348 alias: &str, 1349 km_uuid: Uuid, 1350 create_new_key: F, 1351 ) -> Result<(KeyIdGuard, KeyEntry)> 1352 where 1353 F: Fn() -> Result<(Vec<u8>, BlobMetaData)>, 1354 { 1355 let _wp = wd::watch_millis("KeystoreDB::get_or_create_key_with", 500); 1356 1357 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1358 let id = { 1359 let mut stmt = tx 1360 .prepare( 1361 "SELECT id FROM persistent.keyentry 1362 WHERE 1363 key_type = ? 1364 AND domain = ? 1365 AND namespace = ? 1366 AND alias = ? 1367 AND state = ?;", 1368 ) 1369 .context("In get_or_create_key_with: Failed to select from keyentry table.")?; 1370 let mut rows = stmt 1371 .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live]) 1372 .context("In get_or_create_key_with: Failed to query from keyentry table.")?; 1373 1374 db_utils::with_rows_extract_one(&mut rows, |row| { 1375 Ok(match row { 1376 Some(r) => r.get(0).context("Failed to unpack id.")?, 1377 None => None, 1378 }) 1379 }) 1380 .context("In get_or_create_key_with.")? 1381 }; 1382 1383 let (id, entry) = match id { 1384 Some(id) => ( 1385 id, 1386 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id) 1387 .context("In get_or_create_key_with.")?, 1388 ), 1389 1390 None => { 1391 let id = Self::insert_with_retry(|id| { 1392 tx.execute( 1393 "INSERT into persistent.keyentry 1394 (id, key_type, domain, namespace, alias, state, km_uuid) 1395 VALUES(?, ?, ?, ?, ?, ?, ?);", 1396 params![ 1397 id, 1398 KeyType::Super, 1399 domain.0, 1400 namespace, 1401 alias, 1402 KeyLifeCycle::Live, 1403 km_uuid, 1404 ], 1405 ) 1406 }) 1407 .context("In get_or_create_key_with.")?; 1408 1409 let (blob, metadata) = 1410 create_new_key().context("In get_or_create_key_with.")?; 1411 Self::set_blob_internal( 1412 &tx, 1413 id, 1414 SubComponentType::KEY_BLOB, 1415 Some(&blob), 1416 Some(&metadata), 1417 ) 1418 .context("In get_or_create_key_with.")?; 1419 ( 1420 id, 1421 KeyEntry { 1422 id, 1423 key_blob_info: Some((blob, metadata)), 1424 pure_cert: false, 1425 ..Default::default() 1426 }, 1427 ) 1428 } 1429 }; 1430 Ok((KEY_ID_LOCK.get(id), entry)).no_gc() 1431 }) 1432 .context("In get_or_create_key_with.") 1433 } 1434 1435 /// Creates a transaction with the given behavior and executes f with the new transaction. 1436 /// The transaction is committed only if f returns Ok and retried if DatabaseBusy 1437 /// or DatabaseLocked is encountered. with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T> where F: Fn(&Transaction) -> Result<(bool, T)>,1438 fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T> 1439 where 1440 F: Fn(&Transaction) -> Result<(bool, T)>, 1441 { 1442 loop { 1443 match self 1444 .conn 1445 .transaction_with_behavior(behavior) 1446 .context("In with_transaction.") 1447 .and_then(|tx| f(&tx).map(|result| (result, tx))) 1448 .and_then(|(result, tx)| { 1449 tx.commit().context("In with_transaction: Failed to commit transaction.")?; 1450 Ok(result) 1451 }) { 1452 Ok(result) => break Ok(result), 1453 Err(e) => { 1454 if Self::is_locked_error(&e) { 1455 std::thread::sleep(std::time::Duration::from_micros(500)); 1456 continue; 1457 } else { 1458 return Err(e).context("In with_transaction."); 1459 } 1460 } 1461 } 1462 } 1463 .map(|(need_gc, result)| { 1464 if need_gc { 1465 if let Some(ref gc) = self.gc { 1466 gc.notify_gc(); 1467 } 1468 } 1469 result 1470 }) 1471 } 1472 is_locked_error(e: &anyhow::Error) -> bool1473 fn is_locked_error(e: &anyhow::Error) -> bool { 1474 matches!( 1475 e.root_cause().downcast_ref::<rusqlite::ffi::Error>(), 1476 Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseBusy, .. }) 1477 | Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseLocked, .. }) 1478 ) 1479 } 1480 1481 /// Creates a new key entry and allocates a new randomized id for the new key. 1482 /// The key id gets associated with a domain and namespace but not with an alias. 1483 /// To complete key generation `rebind_alias` should be called after all of the 1484 /// key artifacts, i.e., blobs and parameters have been associated with the new 1485 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry 1486 /// atomic even if key generation is not. create_key_entry( &mut self, domain: &Domain, namespace: &i64, key_type: KeyType, km_uuid: &Uuid, ) -> Result<KeyIdGuard>1487 pub fn create_key_entry( 1488 &mut self, 1489 domain: &Domain, 1490 namespace: &i64, 1491 key_type: KeyType, 1492 km_uuid: &Uuid, 1493 ) -> Result<KeyIdGuard> { 1494 let _wp = wd::watch_millis("KeystoreDB::create_key_entry", 500); 1495 1496 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1497 Self::create_key_entry_internal(tx, domain, namespace, key_type, km_uuid).no_gc() 1498 }) 1499 .context("In create_key_entry.") 1500 } 1501 create_key_entry_internal( tx: &Transaction, domain: &Domain, namespace: &i64, key_type: KeyType, km_uuid: &Uuid, ) -> Result<KeyIdGuard>1502 fn create_key_entry_internal( 1503 tx: &Transaction, 1504 domain: &Domain, 1505 namespace: &i64, 1506 key_type: KeyType, 1507 km_uuid: &Uuid, 1508 ) -> Result<KeyIdGuard> { 1509 match *domain { 1510 Domain::APP | Domain::SELINUX => {} 1511 _ => { 1512 return Err(KsError::sys()) 1513 .context(format!("Domain {:?} must be either App or SELinux.", domain)); 1514 } 1515 } 1516 Ok(KEY_ID_LOCK.get( 1517 Self::insert_with_retry(|id| { 1518 tx.execute( 1519 "INSERT into persistent.keyentry 1520 (id, key_type, domain, namespace, alias, state, km_uuid) 1521 VALUES(?, ?, ?, ?, NULL, ?, ?);", 1522 params![ 1523 id, 1524 key_type, 1525 domain.0 as u32, 1526 *namespace, 1527 KeyLifeCycle::Existing, 1528 km_uuid, 1529 ], 1530 ) 1531 }) 1532 .context("In create_key_entry_internal")?, 1533 )) 1534 } 1535 1536 /// Creates a new attestation key entry and allocates a new randomized id for the new key. 1537 /// The key id gets associated with a domain and namespace later but not with an alias. The 1538 /// alias will be used to denote if a key has been signed as each key can only be bound to one 1539 /// domain and namespace pairing so there is no need to use them as a value for indexing into 1540 /// a key. create_attestation_key_entry( &mut self, maced_public_key: &[u8], raw_public_key: &[u8], private_key: &[u8], km_uuid: &Uuid, ) -> Result<()>1541 pub fn create_attestation_key_entry( 1542 &mut self, 1543 maced_public_key: &[u8], 1544 raw_public_key: &[u8], 1545 private_key: &[u8], 1546 km_uuid: &Uuid, 1547 ) -> Result<()> { 1548 let _wp = wd::watch_millis("KeystoreDB::create_attestation_key_entry", 500); 1549 1550 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1551 let key_id = KEY_ID_LOCK.get( 1552 Self::insert_with_retry(|id| { 1553 tx.execute( 1554 "INSERT into persistent.keyentry 1555 (id, key_type, domain, namespace, alias, state, km_uuid) 1556 VALUES(?, ?, NULL, NULL, NULL, ?, ?);", 1557 params![id, KeyType::Attestation, KeyLifeCycle::Live, km_uuid], 1558 ) 1559 }) 1560 .context("In create_key_entry")?, 1561 ); 1562 Self::set_blob_internal( 1563 &tx, 1564 key_id.0, 1565 SubComponentType::KEY_BLOB, 1566 Some(private_key), 1567 None, 1568 )?; 1569 let mut metadata = KeyMetaData::new(); 1570 metadata.add(KeyMetaEntry::AttestationMacedPublicKey(maced_public_key.to_vec())); 1571 metadata.add(KeyMetaEntry::AttestationRawPubKey(raw_public_key.to_vec())); 1572 metadata.store_in_db(key_id.0, &tx)?; 1573 Ok(()).no_gc() 1574 }) 1575 .context("In create_attestation_key_entry") 1576 } 1577 1578 /// Set a new blob and associates it with the given key id. Each blob 1579 /// has a sub component type. 1580 /// Each key can have one of each sub component type associated. If more 1581 /// are added only the most recent can be retrieved, and superseded blobs 1582 /// will get garbage collected. 1583 /// Components SubComponentType::CERT and SubComponentType::CERT_CHAIN can be 1584 /// removed by setting blob to None. set_blob( &mut self, key_id: &KeyIdGuard, sc_type: SubComponentType, blob: Option<&[u8]>, blob_metadata: Option<&BlobMetaData>, ) -> Result<()>1585 pub fn set_blob( 1586 &mut self, 1587 key_id: &KeyIdGuard, 1588 sc_type: SubComponentType, 1589 blob: Option<&[u8]>, 1590 blob_metadata: Option<&BlobMetaData>, 1591 ) -> Result<()> { 1592 let _wp = wd::watch_millis("KeystoreDB::set_blob", 500); 1593 1594 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1595 Self::set_blob_internal(&tx, key_id.0, sc_type, blob, blob_metadata).need_gc() 1596 }) 1597 .context("In set_blob.") 1598 } 1599 1600 /// Why would we insert a deleted blob? This weird function is for the purpose of legacy 1601 /// key migration in the case where we bulk delete all the keys of an app or even a user. 1602 /// We use this to insert key blobs into the database which can then be garbage collected 1603 /// lazily by the key garbage collector. set_deleted_blob(&mut self, blob: &[u8], blob_metadata: &BlobMetaData) -> Result<()>1604 pub fn set_deleted_blob(&mut self, blob: &[u8], blob_metadata: &BlobMetaData) -> Result<()> { 1605 let _wp = wd::watch_millis("KeystoreDB::set_deleted_blob", 500); 1606 1607 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1608 Self::set_blob_internal( 1609 &tx, 1610 Self::UNASSIGNED_KEY_ID, 1611 SubComponentType::KEY_BLOB, 1612 Some(blob), 1613 Some(blob_metadata), 1614 ) 1615 .need_gc() 1616 }) 1617 .context("In set_deleted_blob.") 1618 } 1619 set_blob_internal( tx: &Transaction, key_id: i64, sc_type: SubComponentType, blob: Option<&[u8]>, blob_metadata: Option<&BlobMetaData>, ) -> Result<()>1620 fn set_blob_internal( 1621 tx: &Transaction, 1622 key_id: i64, 1623 sc_type: SubComponentType, 1624 blob: Option<&[u8]>, 1625 blob_metadata: Option<&BlobMetaData>, 1626 ) -> Result<()> { 1627 match (blob, sc_type) { 1628 (Some(blob), _) => { 1629 tx.execute( 1630 "INSERT INTO persistent.blobentry 1631 (subcomponent_type, keyentryid, blob) VALUES (?, ?, ?);", 1632 params![sc_type, key_id, blob], 1633 ) 1634 .context("In set_blob_internal: Failed to insert blob.")?; 1635 if let Some(blob_metadata) = blob_metadata { 1636 let blob_id = tx 1637 .query_row("SELECT MAX(id) FROM persistent.blobentry;", NO_PARAMS, |row| { 1638 row.get(0) 1639 }) 1640 .context("In set_blob_internal: Failed to get new blob id.")?; 1641 blob_metadata 1642 .store_in_db(blob_id, tx) 1643 .context("In set_blob_internal: Trying to store blob metadata.")?; 1644 } 1645 } 1646 (None, SubComponentType::CERT) | (None, SubComponentType::CERT_CHAIN) => { 1647 tx.execute( 1648 "DELETE FROM persistent.blobentry 1649 WHERE subcomponent_type = ? AND keyentryid = ?;", 1650 params![sc_type, key_id], 1651 ) 1652 .context("In set_blob_internal: Failed to delete blob.")?; 1653 } 1654 (None, _) => { 1655 return Err(KsError::sys()) 1656 .context("In set_blob_internal: Other blobs cannot be deleted in this way."); 1657 } 1658 } 1659 Ok(()) 1660 } 1661 1662 /// Inserts a collection of key parameters into the `persistent.keyparameter` table 1663 /// and associates them with the given `key_id`. 1664 #[cfg(test)] insert_keyparameter(&mut self, key_id: &KeyIdGuard, params: &[KeyParameter]) -> Result<()>1665 fn insert_keyparameter(&mut self, key_id: &KeyIdGuard, params: &[KeyParameter]) -> Result<()> { 1666 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1667 Self::insert_keyparameter_internal(tx, key_id, params).no_gc() 1668 }) 1669 .context("In insert_keyparameter.") 1670 } 1671 insert_keyparameter_internal( tx: &Transaction, key_id: &KeyIdGuard, params: &[KeyParameter], ) -> Result<()>1672 fn insert_keyparameter_internal( 1673 tx: &Transaction, 1674 key_id: &KeyIdGuard, 1675 params: &[KeyParameter], 1676 ) -> Result<()> { 1677 let mut stmt = tx 1678 .prepare( 1679 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level) 1680 VALUES (?, ?, ?, ?);", 1681 ) 1682 .context("In insert_keyparameter_internal: Failed to prepare statement.")?; 1683 1684 for p in params.iter() { 1685 stmt.insert(params![ 1686 key_id.0, 1687 p.get_tag().0, 1688 p.key_parameter_value(), 1689 p.security_level().0 1690 ]) 1691 .with_context(|| { 1692 format!("In insert_keyparameter_internal: Failed to insert {:?}", p) 1693 })?; 1694 } 1695 Ok(()) 1696 } 1697 1698 /// Insert a set of key entry specific metadata into the database. 1699 #[cfg(test)] insert_key_metadata(&mut self, key_id: &KeyIdGuard, metadata: &KeyMetaData) -> Result<()>1700 fn insert_key_metadata(&mut self, key_id: &KeyIdGuard, metadata: &KeyMetaData) -> Result<()> { 1701 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1702 metadata.store_in_db(key_id.0, &tx).no_gc() 1703 }) 1704 .context("In insert_key_metadata.") 1705 } 1706 1707 /// Stores a signed certificate chain signed by a remote provisioning server, keyed 1708 /// on the public key. store_signed_attestation_certificate_chain( &mut self, raw_public_key: &[u8], batch_cert: &[u8], cert_chain: &[u8], expiration_date: i64, km_uuid: &Uuid, ) -> Result<()>1709 pub fn store_signed_attestation_certificate_chain( 1710 &mut self, 1711 raw_public_key: &[u8], 1712 batch_cert: &[u8], 1713 cert_chain: &[u8], 1714 expiration_date: i64, 1715 km_uuid: &Uuid, 1716 ) -> Result<()> { 1717 let _wp = wd::watch_millis("KeystoreDB::store_signed_attestation_certificate_chain", 500); 1718 1719 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1720 let mut stmt = tx 1721 .prepare( 1722 "SELECT keyentryid 1723 FROM persistent.keymetadata 1724 WHERE tag = ? AND data = ? AND keyentryid IN 1725 (SELECT id 1726 FROM persistent.keyentry 1727 WHERE 1728 alias IS NULL AND 1729 domain IS NULL AND 1730 namespace IS NULL AND 1731 key_type = ? AND 1732 km_uuid = ?);", 1733 ) 1734 .context("Failed to store attestation certificate chain.")?; 1735 let mut rows = stmt 1736 .query(params![ 1737 KeyMetaData::AttestationRawPubKey, 1738 raw_public_key, 1739 KeyType::Attestation, 1740 km_uuid 1741 ]) 1742 .context("Failed to fetch keyid")?; 1743 let key_id = db_utils::with_rows_extract_one(&mut rows, |row| { 1744 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)? 1745 .get(0) 1746 .context("Failed to unpack id.") 1747 }) 1748 .context("Failed to get key_id.")?; 1749 let num_updated = tx 1750 .execute( 1751 "UPDATE persistent.keyentry 1752 SET alias = ? 1753 WHERE id = ?;", 1754 params!["signed", key_id], 1755 ) 1756 .context("Failed to update alias.")?; 1757 if num_updated != 1 { 1758 return Err(KsError::sys()).context("Alias not updated for the key."); 1759 } 1760 let mut metadata = KeyMetaData::new(); 1761 metadata.add(KeyMetaEntry::AttestationExpirationDate(DateTime::from_millis_epoch( 1762 expiration_date, 1763 ))); 1764 metadata.store_in_db(key_id, &tx).context("Failed to insert key metadata.")?; 1765 Self::set_blob_internal( 1766 &tx, 1767 key_id, 1768 SubComponentType::CERT_CHAIN, 1769 Some(cert_chain), 1770 None, 1771 ) 1772 .context("Failed to insert cert chain")?; 1773 Self::set_blob_internal(&tx, key_id, SubComponentType::CERT, Some(batch_cert), None) 1774 .context("Failed to insert cert")?; 1775 Ok(()).no_gc() 1776 }) 1777 .context("In store_signed_attestation_certificate_chain: ") 1778 } 1779 1780 /// Assigns the next unassigned attestation key to a domain/namespace combo that does not 1781 /// currently have a key assigned to it. assign_attestation_key( &mut self, domain: Domain, namespace: i64, km_uuid: &Uuid, ) -> Result<()>1782 pub fn assign_attestation_key( 1783 &mut self, 1784 domain: Domain, 1785 namespace: i64, 1786 km_uuid: &Uuid, 1787 ) -> Result<()> { 1788 let _wp = wd::watch_millis("KeystoreDB::assign_attestation_key", 500); 1789 1790 match domain { 1791 Domain::APP | Domain::SELINUX => {} 1792 _ => { 1793 return Err(KsError::sys()).context(format!( 1794 concat!( 1795 "In assign_attestation_key: Domain {:?} ", 1796 "must be either App or SELinux.", 1797 ), 1798 domain 1799 )); 1800 } 1801 } 1802 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1803 let result = tx 1804 .execute( 1805 "UPDATE persistent.keyentry 1806 SET domain=?1, namespace=?2 1807 WHERE 1808 id = 1809 (SELECT MIN(id) 1810 FROM persistent.keyentry 1811 WHERE ALIAS IS NOT NULL 1812 AND domain IS NULL 1813 AND key_type IS ?3 1814 AND state IS ?4 1815 AND km_uuid IS ?5) 1816 AND 1817 (SELECT COUNT(*) 1818 FROM persistent.keyentry 1819 WHERE domain=?1 1820 AND namespace=?2 1821 AND key_type IS ?3 1822 AND state IS ?4 1823 AND km_uuid IS ?5) = 0;", 1824 params![ 1825 domain.0 as u32, 1826 namespace, 1827 KeyType::Attestation, 1828 KeyLifeCycle::Live, 1829 km_uuid, 1830 ], 1831 ) 1832 .context("Failed to assign attestation key")?; 1833 if result == 0 { 1834 log_rkp_error_stats(MetricsRkpError::OUT_OF_KEYS); 1835 return Err(KsError::Rc(ResponseCode::OUT_OF_KEYS)).context("Out of keys."); 1836 } else if result > 1 { 1837 return Err(KsError::sys()) 1838 .context(format!("Expected to update 1 entry, instead updated {}", result)); 1839 } 1840 Ok(()).no_gc() 1841 }) 1842 .context("In assign_attestation_key: ") 1843 } 1844 1845 /// Retrieves num_keys number of attestation keys that have not yet been signed by a remote 1846 /// provisioning server, or the maximum number available if there are not num_keys number of 1847 /// entries in the table. fetch_unsigned_attestation_keys( &mut self, num_keys: i32, km_uuid: &Uuid, ) -> Result<Vec<Vec<u8>>>1848 pub fn fetch_unsigned_attestation_keys( 1849 &mut self, 1850 num_keys: i32, 1851 km_uuid: &Uuid, 1852 ) -> Result<Vec<Vec<u8>>> { 1853 let _wp = wd::watch_millis("KeystoreDB::fetch_unsigned_attestation_keys", 500); 1854 1855 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1856 let mut stmt = tx 1857 .prepare( 1858 "SELECT data 1859 FROM persistent.keymetadata 1860 WHERE tag = ? AND keyentryid IN 1861 (SELECT id 1862 FROM persistent.keyentry 1863 WHERE 1864 alias IS NULL AND 1865 domain IS NULL AND 1866 namespace IS NULL AND 1867 key_type = ? AND 1868 km_uuid = ? 1869 LIMIT ?);", 1870 ) 1871 .context("Failed to prepare statement")?; 1872 let rows = stmt 1873 .query_map( 1874 params![ 1875 KeyMetaData::AttestationMacedPublicKey, 1876 KeyType::Attestation, 1877 km_uuid, 1878 num_keys 1879 ], 1880 |row| row.get(0), 1881 )? 1882 .collect::<rusqlite::Result<Vec<Vec<u8>>>>() 1883 .context("Failed to execute statement")?; 1884 Ok(rows).no_gc() 1885 }) 1886 .context("In fetch_unsigned_attestation_keys") 1887 } 1888 1889 /// Removes any keys that have expired as of the current time. Returns the number of keys 1890 /// marked unreferenced that are bound to be garbage collected. delete_expired_attestation_keys(&mut self) -> Result<i32>1891 pub fn delete_expired_attestation_keys(&mut self) -> Result<i32> { 1892 let _wp = wd::watch_millis("KeystoreDB::delete_expired_attestation_keys", 500); 1893 1894 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1895 let mut stmt = tx 1896 .prepare( 1897 "SELECT keyentryid, data 1898 FROM persistent.keymetadata 1899 WHERE tag = ? AND keyentryid IN 1900 (SELECT id 1901 FROM persistent.keyentry 1902 WHERE key_type = ?);", 1903 ) 1904 .context("Failed to prepare query")?; 1905 let key_ids_to_check = stmt 1906 .query_map( 1907 params![KeyMetaData::AttestationExpirationDate, KeyType::Attestation], 1908 |row| Ok((row.get(0)?, row.get(1)?)), 1909 )? 1910 .collect::<rusqlite::Result<Vec<(i64, DateTime)>>>() 1911 .context("Failed to get date metadata")?; 1912 let curr_time = DateTime::from_millis_epoch( 1913 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64, 1914 ); 1915 let mut num_deleted = 0; 1916 for id in key_ids_to_check.iter().filter(|kt| kt.1 < curr_time).map(|kt| kt.0) { 1917 if Self::mark_unreferenced(&tx, id)? { 1918 num_deleted += 1; 1919 } 1920 } 1921 Ok(num_deleted).do_gc(num_deleted != 0) 1922 }) 1923 .context("In delete_expired_attestation_keys: ") 1924 } 1925 1926 /// Deletes all remotely provisioned attestation keys in the system, regardless of the state 1927 /// they are in. This is useful primarily as a testing mechanism. delete_all_attestation_keys(&mut self) -> Result<i64>1928 pub fn delete_all_attestation_keys(&mut self) -> Result<i64> { 1929 let _wp = wd::watch_millis("KeystoreDB::delete_all_attestation_keys", 500); 1930 1931 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1932 let mut stmt = tx 1933 .prepare( 1934 "SELECT id FROM persistent.keyentry 1935 WHERE key_type IS ?;", 1936 ) 1937 .context("Failed to prepare statement")?; 1938 let keys_to_delete = stmt 1939 .query_map(params![KeyType::Attestation], |row| row.get(0))? 1940 .collect::<rusqlite::Result<Vec<i64>>>() 1941 .context("Failed to execute statement")?; 1942 let num_deleted = keys_to_delete 1943 .iter() 1944 .map(|id| Self::mark_unreferenced(&tx, *id)) 1945 .collect::<Result<Vec<bool>>>() 1946 .context("Failed to execute mark_unreferenced on a keyid")? 1947 .into_iter() 1948 .filter(|result| *result) 1949 .count() as i64; 1950 Ok(num_deleted).do_gc(num_deleted != 0) 1951 }) 1952 .context("In delete_all_attestation_keys: ") 1953 } 1954 1955 /// Counts the number of keys that will expire by the provided epoch date and the number of 1956 /// keys not currently assigned to a domain. get_attestation_pool_status( &mut self, date: i64, km_uuid: &Uuid, ) -> Result<AttestationPoolStatus>1957 pub fn get_attestation_pool_status( 1958 &mut self, 1959 date: i64, 1960 km_uuid: &Uuid, 1961 ) -> Result<AttestationPoolStatus> { 1962 let _wp = wd::watch_millis("KeystoreDB::get_attestation_pool_status", 500); 1963 1964 self.with_transaction(TransactionBehavior::Immediate, |tx| { 1965 let mut stmt = tx.prepare( 1966 "SELECT data 1967 FROM persistent.keymetadata 1968 WHERE tag = ? AND keyentryid IN 1969 (SELECT id 1970 FROM persistent.keyentry 1971 WHERE alias IS NOT NULL 1972 AND key_type = ? 1973 AND km_uuid = ? 1974 AND state = ?);", 1975 )?; 1976 let times = stmt 1977 .query_map( 1978 params![ 1979 KeyMetaData::AttestationExpirationDate, 1980 KeyType::Attestation, 1981 km_uuid, 1982 KeyLifeCycle::Live 1983 ], 1984 |row| row.get(0), 1985 )? 1986 .collect::<rusqlite::Result<Vec<DateTime>>>() 1987 .context("Failed to execute metadata statement")?; 1988 let expiring = 1989 times.iter().filter(|time| time < &&DateTime::from_millis_epoch(date)).count() 1990 as i32; 1991 stmt = tx.prepare( 1992 "SELECT alias, domain 1993 FROM persistent.keyentry 1994 WHERE key_type = ? AND km_uuid = ? AND state = ?;", 1995 )?; 1996 let rows = stmt 1997 .query_map(params![KeyType::Attestation, km_uuid, KeyLifeCycle::Live], |row| { 1998 Ok((row.get(0)?, row.get(1)?)) 1999 })? 2000 .collect::<rusqlite::Result<Vec<(Option<String>, Option<u32>)>>>() 2001 .context("Failed to execute keyentry statement")?; 2002 let mut unassigned = 0i32; 2003 let mut attested = 0i32; 2004 let total = rows.len() as i32; 2005 for (alias, domain) in rows { 2006 match (alias, domain) { 2007 (Some(_alias), None) => { 2008 attested += 1; 2009 unassigned += 1; 2010 } 2011 (Some(_alias), Some(_domain)) => { 2012 attested += 1; 2013 } 2014 _ => {} 2015 } 2016 } 2017 Ok(AttestationPoolStatus { expiring, unassigned, attested, total }).no_gc() 2018 }) 2019 .context("In get_attestation_pool_status: ") 2020 } 2021 2022 /// Fetches the private key and corresponding certificate chain assigned to a 2023 /// domain/namespace pair. Will either return nothing if the domain/namespace is 2024 /// not assigned, or one CertificateChain. retrieve_attestation_key_and_cert_chain( &mut self, domain: Domain, namespace: i64, km_uuid: &Uuid, ) -> Result<Option<CertificateChain>>2025 pub fn retrieve_attestation_key_and_cert_chain( 2026 &mut self, 2027 domain: Domain, 2028 namespace: i64, 2029 km_uuid: &Uuid, 2030 ) -> Result<Option<CertificateChain>> { 2031 let _wp = wd::watch_millis("KeystoreDB::retrieve_attestation_key_and_cert_chain", 500); 2032 2033 match domain { 2034 Domain::APP | Domain::SELINUX => {} 2035 _ => { 2036 return Err(KsError::sys()) 2037 .context(format!("Domain {:?} must be either App or SELinux.", domain)); 2038 } 2039 } 2040 self.with_transaction(TransactionBehavior::Deferred, |tx| { 2041 let mut stmt = tx.prepare( 2042 "SELECT subcomponent_type, blob 2043 FROM persistent.blobentry 2044 WHERE keyentryid IN 2045 (SELECT id 2046 FROM persistent.keyentry 2047 WHERE key_type = ? 2048 AND domain = ? 2049 AND namespace = ? 2050 AND state = ? 2051 AND km_uuid = ?);", 2052 )?; 2053 let rows = stmt 2054 .query_map( 2055 params![ 2056 KeyType::Attestation, 2057 domain.0 as u32, 2058 namespace, 2059 KeyLifeCycle::Live, 2060 km_uuid 2061 ], 2062 |row| Ok((row.get(0)?, row.get(1)?)), 2063 )? 2064 .collect::<rusqlite::Result<Vec<(SubComponentType, Vec<u8>)>>>() 2065 .context("query failed.")?; 2066 if rows.is_empty() { 2067 return Ok(None).no_gc(); 2068 } else if rows.len() != 3 { 2069 return Err(KsError::sys()).context(format!( 2070 concat!( 2071 "Expected to get a single attestation", 2072 "key, cert, and cert chain for a total of 3 entries, but instead got {}." 2073 ), 2074 rows.len() 2075 )); 2076 } 2077 let mut km_blob: Vec<u8> = Vec::new(); 2078 let mut cert_chain_blob: Vec<u8> = Vec::new(); 2079 let mut batch_cert_blob: Vec<u8> = Vec::new(); 2080 for row in rows { 2081 let sub_type: SubComponentType = row.0; 2082 match sub_type { 2083 SubComponentType::KEY_BLOB => { 2084 km_blob = row.1; 2085 } 2086 SubComponentType::CERT_CHAIN => { 2087 cert_chain_blob = row.1; 2088 } 2089 SubComponentType::CERT => { 2090 batch_cert_blob = row.1; 2091 } 2092 _ => Err(KsError::sys()).context("Unknown or incorrect subcomponent type.")?, 2093 } 2094 } 2095 Ok(Some(CertificateChain { 2096 private_key: ZVec::try_from(km_blob)?, 2097 batch_cert: batch_cert_blob, 2098 cert_chain: cert_chain_blob, 2099 })) 2100 .no_gc() 2101 }) 2102 .context("In retrieve_attestation_key_and_cert_chain:") 2103 } 2104 2105 /// Updates the alias column of the given key id `newid` with the given alias, 2106 /// and atomically, removes the alias, domain, and namespace from another row 2107 /// with the same alias-domain-namespace tuple if such row exits. 2108 /// Returns Ok(true) if an old key was marked unreferenced as a hint to the garbage 2109 /// collector. rebind_alias( tx: &Transaction, newid: &KeyIdGuard, alias: &str, domain: &Domain, namespace: &i64, key_type: KeyType, ) -> Result<bool>2110 fn rebind_alias( 2111 tx: &Transaction, 2112 newid: &KeyIdGuard, 2113 alias: &str, 2114 domain: &Domain, 2115 namespace: &i64, 2116 key_type: KeyType, 2117 ) -> Result<bool> { 2118 match *domain { 2119 Domain::APP | Domain::SELINUX => {} 2120 _ => { 2121 return Err(KsError::sys()).context(format!( 2122 "In rebind_alias: Domain {:?} must be either App or SELinux.", 2123 domain 2124 )); 2125 } 2126 } 2127 let updated = tx 2128 .execute( 2129 "UPDATE persistent.keyentry 2130 SET alias = NULL, domain = NULL, namespace = NULL, state = ? 2131 WHERE alias = ? AND domain = ? AND namespace = ? AND key_type = ?;", 2132 params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace, key_type], 2133 ) 2134 .context("In rebind_alias: Failed to rebind existing entry.")?; 2135 let result = tx 2136 .execute( 2137 "UPDATE persistent.keyentry 2138 SET alias = ?, state = ? 2139 WHERE id = ? AND domain = ? AND namespace = ? AND state = ? AND key_type = ?;", 2140 params![ 2141 alias, 2142 KeyLifeCycle::Live, 2143 newid.0, 2144 domain.0 as u32, 2145 *namespace, 2146 KeyLifeCycle::Existing, 2147 key_type, 2148 ], 2149 ) 2150 .context("In rebind_alias: Failed to set alias.")?; 2151 if result != 1 { 2152 return Err(KsError::sys()).context(format!( 2153 "In rebind_alias: Expected to update a single entry but instead updated {}.", 2154 result 2155 )); 2156 } 2157 Ok(updated != 0) 2158 } 2159 2160 /// Moves the key given by KeyIdGuard to the new location at `destination`. If the destination 2161 /// is already occupied by a key, this function fails with `ResponseCode::INVALID_ARGUMENT`. migrate_key_namespace( &mut self, key_id_guard: KeyIdGuard, destination: &KeyDescriptor, caller_uid: u32, check_permission: impl Fn(&KeyDescriptor) -> Result<()>, ) -> Result<()>2162 pub fn migrate_key_namespace( 2163 &mut self, 2164 key_id_guard: KeyIdGuard, 2165 destination: &KeyDescriptor, 2166 caller_uid: u32, 2167 check_permission: impl Fn(&KeyDescriptor) -> Result<()>, 2168 ) -> Result<()> { 2169 let _wp = wd::watch_millis("KeystoreDB::migrate_key_namespace", 500); 2170 2171 let destination = match destination.domain { 2172 Domain::APP => KeyDescriptor { nspace: caller_uid as i64, ..(*destination).clone() }, 2173 Domain::SELINUX => (*destination).clone(), 2174 domain => { 2175 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 2176 .context(format!("Domain {:?} must be either APP or SELINUX.", domain)); 2177 } 2178 }; 2179 2180 // Security critical: Must return immediately on failure. Do not remove the '?'; 2181 check_permission(&destination) 2182 .context("In migrate_key_namespace: Trying to check permission.")?; 2183 2184 let alias = destination 2185 .alias 2186 .as_ref() 2187 .ok_or(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 2188 .context("In migrate_key_namespace: Alias must be specified.")?; 2189 2190 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2191 // Query the destination location. If there is a key, the migration request fails. 2192 if tx 2193 .query_row( 2194 "SELECT id FROM persistent.keyentry 2195 WHERE alias = ? AND domain = ? AND namespace = ?;", 2196 params![alias, destination.domain.0, destination.nspace], 2197 |_| Ok(()), 2198 ) 2199 .optional() 2200 .context("Failed to query destination.")? 2201 .is_some() 2202 { 2203 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 2204 .context("Target already exists."); 2205 } 2206 2207 let updated = tx 2208 .execute( 2209 "UPDATE persistent.keyentry 2210 SET alias = ?, domain = ?, namespace = ? 2211 WHERE id = ?;", 2212 params![alias, destination.domain.0, destination.nspace, key_id_guard.id()], 2213 ) 2214 .context("Failed to update key entry.")?; 2215 2216 if updated != 1 { 2217 return Err(KsError::sys()) 2218 .context(format!("Update succeeded, but {} rows were updated.", updated)); 2219 } 2220 Ok(()).no_gc() 2221 }) 2222 .context("In migrate_key_namespace:") 2223 } 2224 2225 /// Store a new key in a single transaction. 2226 /// The function creates a new key entry, populates the blob, key parameter, and metadata 2227 /// fields, and rebinds the given alias to the new key. 2228 /// The boolean returned is a hint for the garbage collector. If true, a key was replaced, 2229 /// is now unreferenced and needs to be collected. 2230 #[allow(clippy::clippy::too_many_arguments)] store_new_key( &mut self, key: &KeyDescriptor, key_type: KeyType, params: &[KeyParameter], blob_info: &(&[u8], &BlobMetaData), cert_info: &CertificateInfo, metadata: &KeyMetaData, km_uuid: &Uuid, ) -> Result<KeyIdGuard>2231 pub fn store_new_key( 2232 &mut self, 2233 key: &KeyDescriptor, 2234 key_type: KeyType, 2235 params: &[KeyParameter], 2236 blob_info: &(&[u8], &BlobMetaData), 2237 cert_info: &CertificateInfo, 2238 metadata: &KeyMetaData, 2239 km_uuid: &Uuid, 2240 ) -> Result<KeyIdGuard> { 2241 let _wp = wd::watch_millis("KeystoreDB::store_new_key", 500); 2242 2243 let (alias, domain, namespace) = match key { 2244 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None } 2245 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => { 2246 (alias, key.domain, nspace) 2247 } 2248 _ => { 2249 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 2250 .context("In store_new_key: Need alias and domain must be APP or SELINUX.") 2251 } 2252 }; 2253 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2254 let key_id = Self::create_key_entry_internal(tx, &domain, namespace, key_type, km_uuid) 2255 .context("Trying to create new key entry.")?; 2256 let (blob, blob_metadata) = *blob_info; 2257 Self::set_blob_internal( 2258 tx, 2259 key_id.id(), 2260 SubComponentType::KEY_BLOB, 2261 Some(blob), 2262 Some(&blob_metadata), 2263 ) 2264 .context("Trying to insert the key blob.")?; 2265 if let Some(cert) = &cert_info.cert { 2266 Self::set_blob_internal(tx, key_id.id(), SubComponentType::CERT, Some(&cert), None) 2267 .context("Trying to insert the certificate.")?; 2268 } 2269 if let Some(cert_chain) = &cert_info.cert_chain { 2270 Self::set_blob_internal( 2271 tx, 2272 key_id.id(), 2273 SubComponentType::CERT_CHAIN, 2274 Some(&cert_chain), 2275 None, 2276 ) 2277 .context("Trying to insert the certificate chain.")?; 2278 } 2279 Self::insert_keyparameter_internal(tx, &key_id, params) 2280 .context("Trying to insert key parameters.")?; 2281 metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?; 2282 let need_gc = Self::rebind_alias(tx, &key_id, &alias, &domain, namespace, key_type) 2283 .context("Trying to rebind alias.")?; 2284 Ok(key_id).do_gc(need_gc) 2285 }) 2286 .context("In store_new_key.") 2287 } 2288 2289 /// Store a new certificate 2290 /// The function creates a new key entry, populates the blob field and metadata, and rebinds 2291 /// the given alias to the new cert. store_new_certificate( &mut self, key: &KeyDescriptor, key_type: KeyType, cert: &[u8], km_uuid: &Uuid, ) -> Result<KeyIdGuard>2292 pub fn store_new_certificate( 2293 &mut self, 2294 key: &KeyDescriptor, 2295 key_type: KeyType, 2296 cert: &[u8], 2297 km_uuid: &Uuid, 2298 ) -> Result<KeyIdGuard> { 2299 let _wp = wd::watch_millis("KeystoreDB::store_new_certificate", 500); 2300 2301 let (alias, domain, namespace) = match key { 2302 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None } 2303 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => { 2304 (alias, key.domain, nspace) 2305 } 2306 _ => { 2307 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)).context( 2308 "In store_new_certificate: Need alias and domain must be APP or SELINUX.", 2309 ) 2310 } 2311 }; 2312 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2313 let key_id = Self::create_key_entry_internal(tx, &domain, namespace, key_type, km_uuid) 2314 .context("Trying to create new key entry.")?; 2315 2316 Self::set_blob_internal( 2317 tx, 2318 key_id.id(), 2319 SubComponentType::CERT_CHAIN, 2320 Some(cert), 2321 None, 2322 ) 2323 .context("Trying to insert certificate.")?; 2324 2325 let mut metadata = KeyMetaData::new(); 2326 metadata.add(KeyMetaEntry::CreationDate( 2327 DateTime::now().context("Trying to make creation time.")?, 2328 )); 2329 2330 metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?; 2331 2332 let need_gc = Self::rebind_alias(tx, &key_id, &alias, &domain, namespace, key_type) 2333 .context("Trying to rebind alias.")?; 2334 Ok(key_id).do_gc(need_gc) 2335 }) 2336 .context("In store_new_certificate.") 2337 } 2338 2339 // Helper function loading the key_id given the key descriptor 2340 // tuple comprising domain, namespace, and alias. 2341 // Requires a valid transaction. load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64>2342 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> { 2343 let alias = key 2344 .alias 2345 .as_ref() 2346 .map_or_else(|| Err(KsError::sys()), Ok) 2347 .context("In load_key_entry_id: Alias must be specified.")?; 2348 let mut stmt = tx 2349 .prepare( 2350 "SELECT id FROM persistent.keyentry 2351 WHERE 2352 key_type = ? 2353 AND domain = ? 2354 AND namespace = ? 2355 AND alias = ? 2356 AND state = ?;", 2357 ) 2358 .context("In load_key_entry_id: Failed to select from keyentry table.")?; 2359 let mut rows = stmt 2360 .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live]) 2361 .context("In load_key_entry_id: Failed to read from keyentry table.")?; 2362 db_utils::with_rows_extract_one(&mut rows, |row| { 2363 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)? 2364 .get(0) 2365 .context("Failed to unpack id.") 2366 }) 2367 .context("In load_key_entry_id.") 2368 } 2369 2370 /// This helper function completes the access tuple of a key, which is required 2371 /// to perform access control. The strategy depends on the `domain` field in the 2372 /// key descriptor. 2373 /// * Domain::SELINUX: The access tuple is complete and this function only loads 2374 /// the key_id for further processing. 2375 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid` 2376 /// which serves as the namespace. 2377 /// * Domain::GRANT: The grant table is queried for the `key_id` and the 2378 /// `access_vector`. 2379 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and 2380 /// `namespace`. 2381 /// In each case the information returned is sufficient to perform the access 2382 /// check and the key id can be used to load further key artifacts. load_access_tuple( tx: &Transaction, key: &KeyDescriptor, key_type: KeyType, caller_uid: u32, ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)>2383 fn load_access_tuple( 2384 tx: &Transaction, 2385 key: &KeyDescriptor, 2386 key_type: KeyType, 2387 caller_uid: u32, 2388 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> { 2389 match key.domain { 2390 // Domain App or SELinux. In this case we load the key_id from 2391 // the keyentry database for further loading of key components. 2392 // We already have the full access tuple to perform access control. 2393 // The only distinction is that we use the caller_uid instead 2394 // of the caller supplied namespace if the domain field is 2395 // Domain::APP. 2396 Domain::APP | Domain::SELINUX => { 2397 let mut access_key = key.clone(); 2398 if access_key.domain == Domain::APP { 2399 access_key.nspace = caller_uid as i64; 2400 } 2401 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type) 2402 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?; 2403 2404 Ok((key_id, access_key, None)) 2405 } 2406 2407 // Domain::GRANT. In this case we load the key_id and the access_vector 2408 // from the grant table. 2409 Domain::GRANT => { 2410 let mut stmt = tx 2411 .prepare( 2412 "SELECT keyentryid, access_vector FROM persistent.grant 2413 WHERE grantee = ? AND id = ? AND 2414 (SELECT state FROM persistent.keyentry WHERE id = keyentryid) = ?;", 2415 ) 2416 .context("Domain::GRANT prepare statement failed")?; 2417 let mut rows = stmt 2418 .query(params![caller_uid as i64, key.nspace, KeyLifeCycle::Live]) 2419 .context("Domain:Grant: query failed.")?; 2420 let (key_id, access_vector): (i64, i32) = 2421 db_utils::with_rows_extract_one(&mut rows, |row| { 2422 let r = 2423 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?; 2424 Ok(( 2425 r.get(0).context("Failed to unpack key_id.")?, 2426 r.get(1).context("Failed to unpack access_vector.")?, 2427 )) 2428 }) 2429 .context("Domain::GRANT.")?; 2430 Ok((key_id, key.clone(), Some(access_vector.into()))) 2431 } 2432 2433 // Domain::KEY_ID. In this case we load the domain and namespace from the 2434 // keyentry database because we need them for access control. 2435 Domain::KEY_ID => { 2436 let (domain, namespace): (Domain, i64) = { 2437 let mut stmt = tx 2438 .prepare( 2439 "SELECT domain, namespace FROM persistent.keyentry 2440 WHERE 2441 id = ? 2442 AND state = ?;", 2443 ) 2444 .context("Domain::KEY_ID: prepare statement failed")?; 2445 let mut rows = stmt 2446 .query(params![key.nspace, KeyLifeCycle::Live]) 2447 .context("Domain::KEY_ID: query failed.")?; 2448 db_utils::with_rows_extract_one(&mut rows, |row| { 2449 let r = 2450 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?; 2451 Ok(( 2452 Domain(r.get(0).context("Failed to unpack domain.")?), 2453 r.get(1).context("Failed to unpack namespace.")?, 2454 )) 2455 }) 2456 .context("Domain::KEY_ID.")? 2457 }; 2458 2459 // We may use a key by id after loading it by grant. 2460 // In this case we have to check if the caller has a grant for this particular 2461 // key. We can skip this if we already know that the caller is the owner. 2462 // But we cannot know this if domain is anything but App. E.g. in the case 2463 // of Domain::SELINUX we have to speculatively check for grants because we have to 2464 // consult the SEPolicy before we know if the caller is the owner. 2465 let access_vector: Option<KeyPermSet> = 2466 if domain != Domain::APP || namespace != caller_uid as i64 { 2467 let access_vector: Option<i32> = tx 2468 .query_row( 2469 "SELECT access_vector FROM persistent.grant 2470 WHERE grantee = ? AND keyentryid = ?;", 2471 params![caller_uid as i64, key.nspace], 2472 |row| row.get(0), 2473 ) 2474 .optional() 2475 .context("Domain::KEY_ID: query grant failed.")?; 2476 access_vector.map(|p| p.into()) 2477 } else { 2478 None 2479 }; 2480 2481 let key_id = key.nspace; 2482 let mut access_key: KeyDescriptor = key.clone(); 2483 access_key.domain = domain; 2484 access_key.nspace = namespace; 2485 2486 Ok((key_id, access_key, access_vector)) 2487 } 2488 _ => Err(anyhow!(KsError::sys())), 2489 } 2490 } 2491 load_blob_components( key_id: i64, load_bits: KeyEntryLoadBits, tx: &Transaction, ) -> Result<(bool, Option<(Vec<u8>, BlobMetaData)>, Option<Vec<u8>>, Option<Vec<u8>>)>2492 fn load_blob_components( 2493 key_id: i64, 2494 load_bits: KeyEntryLoadBits, 2495 tx: &Transaction, 2496 ) -> Result<(bool, Option<(Vec<u8>, BlobMetaData)>, Option<Vec<u8>>, Option<Vec<u8>>)> { 2497 let mut stmt = tx 2498 .prepare( 2499 "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry 2500 WHERE keyentryid = ? GROUP BY subcomponent_type;", 2501 ) 2502 .context("In load_blob_components: prepare statement failed.")?; 2503 2504 let mut rows = 2505 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?; 2506 2507 let mut key_blob: Option<(i64, Vec<u8>)> = None; 2508 let mut cert_blob: Option<Vec<u8>> = None; 2509 let mut cert_chain_blob: Option<Vec<u8>> = None; 2510 let mut has_km_blob: bool = false; 2511 db_utils::with_rows_extract_all(&mut rows, |row| { 2512 let sub_type: SubComponentType = 2513 row.get(1).context("Failed to extract subcomponent_type.")?; 2514 has_km_blob = has_km_blob || sub_type == SubComponentType::KEY_BLOB; 2515 match (sub_type, load_bits.load_public(), load_bits.load_km()) { 2516 (SubComponentType::KEY_BLOB, _, true) => { 2517 key_blob = Some(( 2518 row.get(0).context("Failed to extract key blob id.")?, 2519 row.get(2).context("Failed to extract key blob.")?, 2520 )); 2521 } 2522 (SubComponentType::CERT, true, _) => { 2523 cert_blob = 2524 Some(row.get(2).context("Failed to extract public certificate blob.")?); 2525 } 2526 (SubComponentType::CERT_CHAIN, true, _) => { 2527 cert_chain_blob = 2528 Some(row.get(2).context("Failed to extract certificate chain blob.")?); 2529 } 2530 (SubComponentType::CERT, _, _) 2531 | (SubComponentType::CERT_CHAIN, _, _) 2532 | (SubComponentType::KEY_BLOB, _, _) => {} 2533 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?, 2534 } 2535 Ok(()) 2536 }) 2537 .context("In load_blob_components.")?; 2538 2539 let blob_info = key_blob.map_or::<Result<_>, _>(Ok(None), |(blob_id, blob)| { 2540 Ok(Some(( 2541 blob, 2542 BlobMetaData::load_from_db(blob_id, tx) 2543 .context("In load_blob_components: Trying to load blob_metadata.")?, 2544 ))) 2545 })?; 2546 2547 Ok((has_km_blob, blob_info, cert_blob, cert_chain_blob)) 2548 } 2549 load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>>2550 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> { 2551 let mut stmt = tx 2552 .prepare( 2553 "SELECT tag, data, security_level from persistent.keyparameter 2554 WHERE keyentryid = ?;", 2555 ) 2556 .context("In load_key_parameters: prepare statement failed.")?; 2557 2558 let mut parameters: Vec<KeyParameter> = Vec::new(); 2559 2560 let mut rows = 2561 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?; 2562 db_utils::with_rows_extract_all(&mut rows, |row| { 2563 let tag = Tag(row.get(0).context("Failed to read tag.")?); 2564 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?); 2565 parameters.push( 2566 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level) 2567 .context("Failed to read KeyParameter.")?, 2568 ); 2569 Ok(()) 2570 }) 2571 .context("In load_key_parameters.")?; 2572 2573 Ok(parameters) 2574 } 2575 2576 /// Decrements the usage count of a limited use key. This function first checks whether the 2577 /// usage has been exhausted, if not, decreases the usage count. If the usage count reaches 2578 /// zero, the key also gets marked unreferenced and scheduled for deletion. 2579 /// Returns Ok(true) if the key was marked unreferenced as a hint to the garbage collector. check_and_update_key_usage_count(&mut self, key_id: i64) -> Result<()>2580 pub fn check_and_update_key_usage_count(&mut self, key_id: i64) -> Result<()> { 2581 let _wp = wd::watch_millis("KeystoreDB::check_and_update_key_usage_count", 500); 2582 2583 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2584 let limit: Option<i32> = tx 2585 .query_row( 2586 "SELECT data FROM persistent.keyparameter WHERE keyentryid = ? AND tag = ?;", 2587 params![key_id, Tag::USAGE_COUNT_LIMIT.0], 2588 |row| row.get(0), 2589 ) 2590 .optional() 2591 .context("Trying to load usage count")?; 2592 2593 let limit = limit 2594 .ok_or(KsError::Km(ErrorCode::INVALID_KEY_BLOB)) 2595 .context("The Key no longer exists. Key is exhausted.")?; 2596 2597 tx.execute( 2598 "UPDATE persistent.keyparameter 2599 SET data = data - 1 2600 WHERE keyentryid = ? AND tag = ? AND data > 0;", 2601 params![key_id, Tag::USAGE_COUNT_LIMIT.0], 2602 ) 2603 .context("Failed to update key usage count.")?; 2604 2605 match limit { 2606 1 => Self::mark_unreferenced(tx, key_id) 2607 .map(|need_gc| (need_gc, ())) 2608 .context("Trying to mark limited use key for deletion."), 2609 0 => Err(KsError::Km(ErrorCode::INVALID_KEY_BLOB)).context("Key is exhausted."), 2610 _ => Ok(()).no_gc(), 2611 } 2612 }) 2613 .context("In check_and_update_key_usage_count.") 2614 } 2615 2616 /// Load a key entry by the given key descriptor. 2617 /// It uses the `check_permission` callback to verify if the access is allowed 2618 /// given the key access tuple read from the database using `load_access_tuple`. 2619 /// With `load_bits` the caller may specify which blobs shall be loaded from 2620 /// the blob database. load_key_entry( &mut self, key: &KeyDescriptor, key_type: KeyType, load_bits: KeyEntryLoadBits, caller_uid: u32, check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, ) -> Result<(KeyIdGuard, KeyEntry)>2621 pub fn load_key_entry( 2622 &mut self, 2623 key: &KeyDescriptor, 2624 key_type: KeyType, 2625 load_bits: KeyEntryLoadBits, 2626 caller_uid: u32, 2627 check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, 2628 ) -> Result<(KeyIdGuard, KeyEntry)> { 2629 let _wp = wd::watch_millis("KeystoreDB::load_key_entry", 500); 2630 2631 loop { 2632 match self.load_key_entry_internal( 2633 key, 2634 key_type, 2635 load_bits, 2636 caller_uid, 2637 &check_permission, 2638 ) { 2639 Ok(result) => break Ok(result), 2640 Err(e) => { 2641 if Self::is_locked_error(&e) { 2642 std::thread::sleep(std::time::Duration::from_micros(500)); 2643 continue; 2644 } else { 2645 return Err(e).context("In load_key_entry."); 2646 } 2647 } 2648 } 2649 } 2650 } 2651 load_key_entry_internal( &mut self, key: &KeyDescriptor, key_type: KeyType, load_bits: KeyEntryLoadBits, caller_uid: u32, check_permission: &impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, ) -> Result<(KeyIdGuard, KeyEntry)>2652 fn load_key_entry_internal( 2653 &mut self, 2654 key: &KeyDescriptor, 2655 key_type: KeyType, 2656 load_bits: KeyEntryLoadBits, 2657 caller_uid: u32, 2658 check_permission: &impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, 2659 ) -> Result<(KeyIdGuard, KeyEntry)> { 2660 // KEY ID LOCK 1/2 2661 // If we got a key descriptor with a key id we can get the lock right away. 2662 // Otherwise we have to defer it until we know the key id. 2663 let key_id_guard = match key.domain { 2664 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)), 2665 _ => None, 2666 }; 2667 2668 let tx = self 2669 .conn 2670 .unchecked_transaction() 2671 .context("In load_key_entry: Failed to initialize transaction.")?; 2672 2673 // Load the key_id and complete the access control tuple. 2674 let (key_id, access_key_descriptor, access_vector) = 2675 Self::load_access_tuple(&tx, key, key_type, caller_uid) 2676 .context("In load_key_entry.")?; 2677 2678 // Perform access control. It is vital that we return here if the permission is denied. 2679 // So do not touch that '?' at the end. 2680 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?; 2681 2682 // KEY ID LOCK 2/2 2683 // If we did not get a key id lock by now, it was because we got a key descriptor 2684 // without a key id. At this point we got the key id, so we can try and get a lock. 2685 // However, we cannot block here, because we are in the middle of the transaction. 2686 // So first we try to get the lock non blocking. If that fails, we roll back the 2687 // transaction and block until we get the lock. After we successfully got the lock, 2688 // we start a new transaction and load the access tuple again. 2689 // 2690 // We don't need to perform access control again, because we already established 2691 // that the caller had access to the given key. But we need to make sure that the 2692 // key id still exists. So we have to load the key entry by key id this time. 2693 let (key_id_guard, tx) = match key_id_guard { 2694 None => match KEY_ID_LOCK.try_get(key_id) { 2695 None => { 2696 // Roll back the transaction. 2697 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?; 2698 2699 // Block until we have a key id lock. 2700 let key_id_guard = KEY_ID_LOCK.get(key_id); 2701 2702 // Create a new transaction. 2703 let tx = self 2704 .conn 2705 .unchecked_transaction() 2706 .context("In load_key_entry: Failed to initialize transaction.")?; 2707 2708 Self::load_access_tuple( 2709 &tx, 2710 // This time we have to load the key by the retrieved key id, because the 2711 // alias may have been rebound after we rolled back the transaction. 2712 &KeyDescriptor { 2713 domain: Domain::KEY_ID, 2714 nspace: key_id, 2715 ..Default::default() 2716 }, 2717 key_type, 2718 caller_uid, 2719 ) 2720 .context("In load_key_entry. (deferred key lock)")?; 2721 (key_id_guard, tx) 2722 } 2723 Some(l) => (l, tx), 2724 }, 2725 Some(key_id_guard) => (key_id_guard, tx), 2726 }; 2727 2728 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id()) 2729 .context("In load_key_entry.")?; 2730 2731 tx.commit().context("In load_key_entry: Failed to commit transaction.")?; 2732 2733 Ok((key_id_guard, key_entry)) 2734 } 2735 mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<bool>2736 fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<bool> { 2737 let updated = tx 2738 .execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id]) 2739 .context("Trying to delete keyentry.")?; 2740 tx.execute("DELETE FROM persistent.keymetadata WHERE keyentryid = ?;", params![key_id]) 2741 .context("Trying to delete keymetadata.")?; 2742 tx.execute("DELETE FROM persistent.keyparameter WHERE keyentryid = ?;", params![key_id]) 2743 .context("Trying to delete keyparameters.")?; 2744 tx.execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id]) 2745 .context("Trying to delete grants.")?; 2746 Ok(updated != 0) 2747 } 2748 2749 /// Marks the given key as unreferenced and removes all of the grants to this key. 2750 /// Returns Ok(true) if a key was marked unreferenced as a hint for the garbage collector. unbind_key( &mut self, key: &KeyDescriptor, key_type: KeyType, caller_uid: u32, check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, ) -> Result<()>2751 pub fn unbind_key( 2752 &mut self, 2753 key: &KeyDescriptor, 2754 key_type: KeyType, 2755 caller_uid: u32, 2756 check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, 2757 ) -> Result<()> { 2758 let _wp = wd::watch_millis("KeystoreDB::unbind_key", 500); 2759 2760 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2761 let (key_id, access_key_descriptor, access_vector) = 2762 Self::load_access_tuple(tx, key, key_type, caller_uid) 2763 .context("Trying to get access tuple.")?; 2764 2765 // Perform access control. It is vital that we return here if the permission is denied. 2766 // So do not touch that '?' at the end. 2767 check_permission(&access_key_descriptor, access_vector) 2768 .context("While checking permission.")?; 2769 2770 Self::mark_unreferenced(tx, key_id) 2771 .map(|need_gc| (need_gc, ())) 2772 .context("Trying to mark the key unreferenced.") 2773 }) 2774 .context("In unbind_key.") 2775 } 2776 get_key_km_uuid(tx: &Transaction, key_id: i64) -> Result<Uuid>2777 fn get_key_km_uuid(tx: &Transaction, key_id: i64) -> Result<Uuid> { 2778 tx.query_row( 2779 "SELECT km_uuid FROM persistent.keyentry WHERE id = ?", 2780 params![key_id], 2781 |row| row.get(0), 2782 ) 2783 .context("In get_key_km_uuid.") 2784 } 2785 2786 /// Delete all artifacts belonging to the namespace given by the domain-namespace tuple. 2787 /// This leaves all of the blob entries orphaned for subsequent garbage collection. unbind_keys_for_namespace(&mut self, domain: Domain, namespace: i64) -> Result<()>2788 pub fn unbind_keys_for_namespace(&mut self, domain: Domain, namespace: i64) -> Result<()> { 2789 let _wp = wd::watch_millis("KeystoreDB::unbind_keys_for_namespace", 500); 2790 2791 if !(domain == Domain::APP || domain == Domain::SELINUX) { 2792 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 2793 .context("In unbind_keys_for_namespace."); 2794 } 2795 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2796 tx.execute( 2797 "DELETE FROM persistent.keymetadata 2798 WHERE keyentryid IN ( 2799 SELECT id FROM persistent.keyentry 2800 WHERE domain = ? AND namespace = ? AND key_type = ? 2801 );", 2802 params![domain.0, namespace, KeyType::Client], 2803 ) 2804 .context("Trying to delete keymetadata.")?; 2805 tx.execute( 2806 "DELETE FROM persistent.keyparameter 2807 WHERE keyentryid IN ( 2808 SELECT id FROM persistent.keyentry 2809 WHERE domain = ? AND namespace = ? AND key_type = ? 2810 );", 2811 params![domain.0, namespace, KeyType::Client], 2812 ) 2813 .context("Trying to delete keyparameters.")?; 2814 tx.execute( 2815 "DELETE FROM persistent.grant 2816 WHERE keyentryid IN ( 2817 SELECT id FROM persistent.keyentry 2818 WHERE domain = ? AND namespace = ? AND key_type = ? 2819 );", 2820 params![domain.0, namespace, KeyType::Client], 2821 ) 2822 .context("Trying to delete grants.")?; 2823 tx.execute( 2824 "DELETE FROM persistent.keyentry 2825 WHERE domain = ? AND namespace = ? AND key_type = ?;", 2826 params![domain.0, namespace, KeyType::Client], 2827 ) 2828 .context("Trying to delete keyentry.")?; 2829 Ok(()).need_gc() 2830 }) 2831 .context("In unbind_keys_for_namespace") 2832 } 2833 cleanup_unreferenced(tx: &Transaction) -> Result<()>2834 fn cleanup_unreferenced(tx: &Transaction) -> Result<()> { 2835 let _wp = wd::watch_millis("KeystoreDB::cleanup_unreferenced", 500); 2836 { 2837 tx.execute( 2838 "DELETE FROM persistent.keymetadata 2839 WHERE keyentryid IN ( 2840 SELECT id FROM persistent.keyentry 2841 WHERE state = ? 2842 );", 2843 params![KeyLifeCycle::Unreferenced], 2844 ) 2845 .context("Trying to delete keymetadata.")?; 2846 tx.execute( 2847 "DELETE FROM persistent.keyparameter 2848 WHERE keyentryid IN ( 2849 SELECT id FROM persistent.keyentry 2850 WHERE state = ? 2851 );", 2852 params![KeyLifeCycle::Unreferenced], 2853 ) 2854 .context("Trying to delete keyparameters.")?; 2855 tx.execute( 2856 "DELETE FROM persistent.grant 2857 WHERE keyentryid IN ( 2858 SELECT id FROM persistent.keyentry 2859 WHERE state = ? 2860 );", 2861 params![KeyLifeCycle::Unreferenced], 2862 ) 2863 .context("Trying to delete grants.")?; 2864 tx.execute( 2865 "DELETE FROM persistent.keyentry 2866 WHERE state = ?;", 2867 params![KeyLifeCycle::Unreferenced], 2868 ) 2869 .context("Trying to delete keyentry.")?; 2870 Result::<()>::Ok(()) 2871 } 2872 .context("In cleanup_unreferenced") 2873 } 2874 2875 /// Delete the keys created on behalf of the user, denoted by the user id. 2876 /// Delete all the keys unless 'keep_non_super_encrypted_keys' set to true. 2877 /// Returned boolean is to hint the garbage collector to delete the unbound keys. 2878 /// The caller of this function should notify the gc if the returned value is true. unbind_keys_for_user( &mut self, user_id: u32, keep_non_super_encrypted_keys: bool, ) -> Result<()>2879 pub fn unbind_keys_for_user( 2880 &mut self, 2881 user_id: u32, 2882 keep_non_super_encrypted_keys: bool, 2883 ) -> Result<()> { 2884 let _wp = wd::watch_millis("KeystoreDB::unbind_keys_for_user", 500); 2885 2886 self.with_transaction(TransactionBehavior::Immediate, |tx| { 2887 let mut stmt = tx 2888 .prepare(&format!( 2889 "SELECT id from persistent.keyentry 2890 WHERE ( 2891 key_type = ? 2892 AND domain = ? 2893 AND cast ( (namespace/{aid_user_offset}) as int) = ? 2894 AND state = ? 2895 ) OR ( 2896 key_type = ? 2897 AND namespace = ? 2898 AND alias = ? 2899 AND state = ? 2900 );", 2901 aid_user_offset = AID_USER_OFFSET 2902 )) 2903 .context(concat!( 2904 "In unbind_keys_for_user. ", 2905 "Failed to prepare the query to find the keys created by apps." 2906 ))?; 2907 2908 let mut rows = stmt 2909 .query(params![ 2910 // WHERE client key: 2911 KeyType::Client, 2912 Domain::APP.0 as u32, 2913 user_id, 2914 KeyLifeCycle::Live, 2915 // OR super key: 2916 KeyType::Super, 2917 user_id, 2918 USER_SUPER_KEY.alias, 2919 KeyLifeCycle::Live 2920 ]) 2921 .context("In unbind_keys_for_user. Failed to query the keys created by apps.")?; 2922 2923 let mut key_ids: Vec<i64> = Vec::new(); 2924 db_utils::with_rows_extract_all(&mut rows, |row| { 2925 key_ids 2926 .push(row.get(0).context("Failed to read key id of a key created by an app.")?); 2927 Ok(()) 2928 }) 2929 .context("In unbind_keys_for_user.")?; 2930 2931 let mut notify_gc = false; 2932 for key_id in key_ids { 2933 if keep_non_super_encrypted_keys { 2934 // Load metadata and filter out non-super-encrypted keys. 2935 if let (_, Some((_, blob_metadata)), _, _) = 2936 Self::load_blob_components(key_id, KeyEntryLoadBits::KM, tx) 2937 .context("In unbind_keys_for_user: Trying to load blob info.")? 2938 { 2939 if blob_metadata.encrypted_by().is_none() { 2940 continue; 2941 } 2942 } 2943 } 2944 notify_gc = Self::mark_unreferenced(&tx, key_id) 2945 .context("In unbind_keys_for_user.")? 2946 || notify_gc; 2947 } 2948 Ok(()).do_gc(notify_gc) 2949 }) 2950 .context("In unbind_keys_for_user.") 2951 } 2952 load_key_components( tx: &Transaction, load_bits: KeyEntryLoadBits, key_id: i64, ) -> Result<KeyEntry>2953 fn load_key_components( 2954 tx: &Transaction, 2955 load_bits: KeyEntryLoadBits, 2956 key_id: i64, 2957 ) -> Result<KeyEntry> { 2958 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?; 2959 2960 let (has_km_blob, key_blob_info, cert_blob, cert_chain_blob) = 2961 Self::load_blob_components(key_id, load_bits, &tx) 2962 .context("In load_key_components.")?; 2963 2964 let parameters = Self::load_key_parameters(key_id, &tx) 2965 .context("In load_key_components: Trying to load key parameters.")?; 2966 2967 let km_uuid = Self::get_key_km_uuid(&tx, key_id) 2968 .context("In load_key_components: Trying to get KM uuid.")?; 2969 2970 Ok(KeyEntry { 2971 id: key_id, 2972 key_blob_info, 2973 cert: cert_blob, 2974 cert_chain: cert_chain_blob, 2975 km_uuid, 2976 parameters, 2977 metadata, 2978 pure_cert: !has_km_blob, 2979 }) 2980 } 2981 2982 /// Returns a list of KeyDescriptors in the selected domain/namespace. 2983 /// The key descriptors will have the domain, nspace, and alias field set. 2984 /// Domain must be APP or SELINUX, the caller must make sure of that. list( &mut self, domain: Domain, namespace: i64, key_type: KeyType, ) -> Result<Vec<KeyDescriptor>>2985 pub fn list( 2986 &mut self, 2987 domain: Domain, 2988 namespace: i64, 2989 key_type: KeyType, 2990 ) -> Result<Vec<KeyDescriptor>> { 2991 let _wp = wd::watch_millis("KeystoreDB::list", 500); 2992 2993 self.with_transaction(TransactionBehavior::Deferred, |tx| { 2994 let mut stmt = tx 2995 .prepare( 2996 "SELECT alias FROM persistent.keyentry 2997 WHERE domain = ? 2998 AND namespace = ? 2999 AND alias IS NOT NULL 3000 AND state = ? 3001 AND key_type = ?;", 3002 ) 3003 .context("In list: Failed to prepare.")?; 3004 3005 let mut rows = stmt 3006 .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live, key_type]) 3007 .context("In list: Failed to query.")?; 3008 3009 let mut descriptors: Vec<KeyDescriptor> = Vec::new(); 3010 db_utils::with_rows_extract_all(&mut rows, |row| { 3011 descriptors.push(KeyDescriptor { 3012 domain, 3013 nspace: namespace, 3014 alias: Some(row.get(0).context("Trying to extract alias.")?), 3015 blob: None, 3016 }); 3017 Ok(()) 3018 }) 3019 .context("In list: Failed to extract rows.")?; 3020 Ok(descriptors).no_gc() 3021 }) 3022 } 3023 3024 /// Adds a grant to the grant table. 3025 /// Like `load_key_entry` this function loads the access tuple before 3026 /// it uses the callback for a permission check. Upon success, 3027 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the 3028 /// grant table. The new row will have a randomized id, which is used as 3029 /// grant id in the namespace field of the resulting KeyDescriptor. grant( &mut self, key: &KeyDescriptor, caller_uid: u32, grantee_uid: u32, access_vector: KeyPermSet, check_permission: impl Fn(&KeyDescriptor, &KeyPermSet) -> Result<()>, ) -> Result<KeyDescriptor>3030 pub fn grant( 3031 &mut self, 3032 key: &KeyDescriptor, 3033 caller_uid: u32, 3034 grantee_uid: u32, 3035 access_vector: KeyPermSet, 3036 check_permission: impl Fn(&KeyDescriptor, &KeyPermSet) -> Result<()>, 3037 ) -> Result<KeyDescriptor> { 3038 let _wp = wd::watch_millis("KeystoreDB::grant", 500); 3039 3040 self.with_transaction(TransactionBehavior::Immediate, |tx| { 3041 // Load the key_id and complete the access control tuple. 3042 // We ignore the access vector here because grants cannot be granted. 3043 // The access vector returned here expresses the permissions the 3044 // grantee has if key.domain == Domain::GRANT. But this vector 3045 // cannot include the grant permission by design, so there is no way the 3046 // subsequent permission check can pass. 3047 // We could check key.domain == Domain::GRANT and fail early. 3048 // But even if we load the access tuple by grant here, the permission 3049 // check denies the attempt to create a grant by grant descriptor. 3050 let (key_id, access_key_descriptor, _) = 3051 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid) 3052 .context("In grant")?; 3053 3054 // Perform access control. It is vital that we return here if the permission 3055 // was denied. So do not touch that '?' at the end of the line. 3056 // This permission check checks if the caller has the grant permission 3057 // for the given key and in addition to all of the permissions 3058 // expressed in `access_vector`. 3059 check_permission(&access_key_descriptor, &access_vector) 3060 .context("In grant: check_permission failed.")?; 3061 3062 let grant_id = if let Some(grant_id) = tx 3063 .query_row( 3064 "SELECT id FROM persistent.grant 3065 WHERE keyentryid = ? AND grantee = ?;", 3066 params![key_id, grantee_uid], 3067 |row| row.get(0), 3068 ) 3069 .optional() 3070 .context("In grant: Failed get optional existing grant id.")? 3071 { 3072 tx.execute( 3073 "UPDATE persistent.grant 3074 SET access_vector = ? 3075 WHERE id = ?;", 3076 params![i32::from(access_vector), grant_id], 3077 ) 3078 .context("In grant: Failed to update existing grant.")?; 3079 grant_id 3080 } else { 3081 Self::insert_with_retry(|id| { 3082 tx.execute( 3083 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector) 3084 VALUES (?, ?, ?, ?);", 3085 params![id, grantee_uid, key_id, i32::from(access_vector)], 3086 ) 3087 }) 3088 .context("In grant")? 3089 }; 3090 3091 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None }) 3092 .no_gc() 3093 }) 3094 } 3095 3096 /// This function checks permissions like `grant` and `load_key_entry` 3097 /// before removing a grant from the grant table. ungrant( &mut self, key: &KeyDescriptor, caller_uid: u32, grantee_uid: u32, check_permission: impl Fn(&KeyDescriptor) -> Result<()>, ) -> Result<()>3098 pub fn ungrant( 3099 &mut self, 3100 key: &KeyDescriptor, 3101 caller_uid: u32, 3102 grantee_uid: u32, 3103 check_permission: impl Fn(&KeyDescriptor) -> Result<()>, 3104 ) -> Result<()> { 3105 let _wp = wd::watch_millis("KeystoreDB::ungrant", 500); 3106 3107 self.with_transaction(TransactionBehavior::Immediate, |tx| { 3108 // Load the key_id and complete the access control tuple. 3109 // We ignore the access vector here because grants cannot be granted. 3110 let (key_id, access_key_descriptor, _) = 3111 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid) 3112 .context("In ungrant.")?; 3113 3114 // Perform access control. We must return here if the permission 3115 // was denied. So do not touch the '?' at the end of this line. 3116 check_permission(&access_key_descriptor) 3117 .context("In grant: check_permission failed.")?; 3118 3119 tx.execute( 3120 "DELETE FROM persistent.grant 3121 WHERE keyentryid = ? AND grantee = ?;", 3122 params![key_id, grantee_uid], 3123 ) 3124 .context("Failed to delete grant.")?; 3125 3126 Ok(()).no_gc() 3127 }) 3128 } 3129 3130 // Generates a random id and passes it to the given function, which will 3131 // try to insert it into a database. If that insertion fails, retry; 3132 // otherwise return the id. insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64>3133 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> { 3134 loop { 3135 let newid: i64 = match random() { 3136 Self::UNASSIGNED_KEY_ID => continue, // UNASSIGNED_KEY_ID cannot be assigned. 3137 i => i, 3138 }; 3139 match inserter(newid) { 3140 // If the id already existed, try again. 3141 Err(rusqlite::Error::SqliteFailure( 3142 libsqlite3_sys::Error { 3143 code: libsqlite3_sys::ErrorCode::ConstraintViolation, 3144 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE, 3145 }, 3146 _, 3147 )) => (), 3148 Err(e) => { 3149 return Err(e).context("In insert_with_retry: failed to insert into database.") 3150 } 3151 _ => return Ok(newid), 3152 } 3153 } 3154 } 3155 3156 /// Insert or replace the auth token based on (user_id, auth_id, auth_type) insert_auth_token(&mut self, auth_token: &HardwareAuthToken)3157 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) { 3158 self.perboot.insert_auth_token_entry(AuthTokenEntry::new( 3159 auth_token.clone(), 3160 MonotonicRawTime::now(), 3161 )) 3162 } 3163 3164 /// Find the newest auth token matching the given predicate. find_auth_token_entry<F>(&self, p: F) -> Option<(AuthTokenEntry, MonotonicRawTime)> where F: Fn(&AuthTokenEntry) -> bool,3165 pub fn find_auth_token_entry<F>(&self, p: F) -> Option<(AuthTokenEntry, MonotonicRawTime)> 3166 where 3167 F: Fn(&AuthTokenEntry) -> bool, 3168 { 3169 self.perboot.find_auth_token_entry(p).map(|entry| (entry, self.get_last_off_body())) 3170 } 3171 3172 /// Insert last_off_body into the metadata table at the initialization of auth token table insert_last_off_body(&self, last_off_body: MonotonicRawTime)3173 pub fn insert_last_off_body(&self, last_off_body: MonotonicRawTime) { 3174 self.perboot.set_last_off_body(last_off_body) 3175 } 3176 3177 /// Update last_off_body when on_device_off_body is called update_last_off_body(&self, last_off_body: MonotonicRawTime)3178 pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) { 3179 self.perboot.set_last_off_body(last_off_body) 3180 } 3181 3182 /// Get last_off_body time when finding auth tokens get_last_off_body(&self) -> MonotonicRawTime3183 fn get_last_off_body(&self) -> MonotonicRawTime { 3184 self.perboot.get_last_off_body() 3185 } 3186 3187 /// Load descriptor of a key by key id load_key_descriptor(&mut self, key_id: i64) -> Result<Option<KeyDescriptor>>3188 pub fn load_key_descriptor(&mut self, key_id: i64) -> Result<Option<KeyDescriptor>> { 3189 let _wp = wd::watch_millis("KeystoreDB::load_key_descriptor", 500); 3190 3191 self.with_transaction(TransactionBehavior::Deferred, |tx| { 3192 tx.query_row( 3193 "SELECT domain, namespace, alias FROM persistent.keyentry WHERE id = ?;", 3194 params![key_id], 3195 |row| { 3196 Ok(KeyDescriptor { 3197 domain: Domain(row.get(0)?), 3198 nspace: row.get(1)?, 3199 alias: row.get(2)?, 3200 blob: None, 3201 }) 3202 }, 3203 ) 3204 .optional() 3205 .context("Trying to load key descriptor") 3206 .no_gc() 3207 }) 3208 .context("In load_key_descriptor.") 3209 } 3210 } 3211 3212 #[cfg(test)] 3213 mod tests { 3214 3215 use super::*; 3216 use crate::key_parameter::{ 3217 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter, 3218 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel, 3219 }; 3220 use crate::key_perm_set; 3221 use crate::permission::{KeyPerm, KeyPermSet}; 3222 use crate::super_key::SuperKeyManager; 3223 use keystore2_test_utils::TempDir; 3224 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ 3225 HardwareAuthToken::HardwareAuthToken, 3226 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type, 3227 }; 3228 use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{ 3229 Timestamp::Timestamp, 3230 }; 3231 use rusqlite::NO_PARAMS; 3232 use rusqlite::TransactionBehavior; 3233 use std::cell::RefCell; 3234 use std::collections::BTreeMap; 3235 use std::fmt::Write; 3236 use std::sync::atomic::{AtomicU8, Ordering}; 3237 use std::sync::Arc; 3238 use std::thread; 3239 use std::time::{Duration, SystemTime}; 3240 #[cfg(disabled)] 3241 use std::time::Instant; 3242 new_test_db() -> Result<KeystoreDB>3243 fn new_test_db() -> Result<KeystoreDB> { 3244 let conn = KeystoreDB::make_connection("file::memory:")?; 3245 3246 let mut db = KeystoreDB { conn, gc: None, perboot: Arc::new(perboot::PerbootDB::new()) }; 3247 db.with_transaction(TransactionBehavior::Immediate, |tx| { 3248 KeystoreDB::init_tables(tx).context("Failed to initialize tables.").no_gc() 3249 })?; 3250 Ok(db) 3251 } 3252 new_test_db_with_gc<F>(path: &Path, cb: F) -> Result<KeystoreDB> where F: Fn(&Uuid, &[u8]) -> Result<()> + Send + 'static,3253 fn new_test_db_with_gc<F>(path: &Path, cb: F) -> Result<KeystoreDB> 3254 where 3255 F: Fn(&Uuid, &[u8]) -> Result<()> + Send + 'static, 3256 { 3257 let super_key: Arc<SuperKeyManager> = Default::default(); 3258 3259 let gc_db = KeystoreDB::new(path, None).expect("Failed to open test gc db_connection."); 3260 let gc = Gc::new_init_with(Default::default(), move || (Box::new(cb), gc_db, super_key)); 3261 3262 KeystoreDB::new(path, Some(Arc::new(gc))) 3263 } 3264 rebind_alias( db: &mut KeystoreDB, newid: &KeyIdGuard, alias: &str, domain: Domain, namespace: i64, ) -> Result<bool>3265 fn rebind_alias( 3266 db: &mut KeystoreDB, 3267 newid: &KeyIdGuard, 3268 alias: &str, 3269 domain: Domain, 3270 namespace: i64, 3271 ) -> Result<bool> { 3272 db.with_transaction(TransactionBehavior::Immediate, |tx| { 3273 KeystoreDB::rebind_alias(tx, newid, alias, &domain, &namespace, KeyType::Client).no_gc() 3274 }) 3275 .context("In rebind_alias.") 3276 } 3277 3278 #[test] datetime() -> Result<()>3279 fn datetime() -> Result<()> { 3280 let conn = Connection::open_in_memory()?; 3281 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?; 3282 let now = SystemTime::now(); 3283 let duration = Duration::from_secs(1000); 3284 let then = now.checked_sub(duration).unwrap(); 3285 let soon = now.checked_add(duration).unwrap(); 3286 conn.execute( 3287 "INSERT INTO test (ts) VALUES (?), (?), (?);", 3288 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?], 3289 )?; 3290 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?; 3291 let mut rows = stmt.query(NO_PARAMS)?; 3292 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?); 3293 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?); 3294 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?); 3295 assert!(rows.next()?.is_none()); 3296 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?); 3297 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?); 3298 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?); 3299 Ok(()) 3300 } 3301 3302 // Ensure that we're using the "injected" random function, not the real one. 3303 #[test] test_mocked_random()3304 fn test_mocked_random() { 3305 let rand1 = random(); 3306 let rand2 = random(); 3307 let rand3 = random(); 3308 if rand1 == rand2 { 3309 assert_eq!(rand2 + 1, rand3); 3310 } else { 3311 assert_eq!(rand1 + 1, rand2); 3312 assert_eq!(rand2, rand3); 3313 } 3314 } 3315 3316 // Test that we have the correct tables. 3317 #[test] test_tables() -> Result<()>3318 fn test_tables() -> Result<()> { 3319 let db = new_test_db()?; 3320 let tables = db 3321 .conn 3322 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")? 3323 .query_map(params![], |row| row.get(0))? 3324 .collect::<rusqlite::Result<Vec<String>>>()?; 3325 assert_eq!(tables.len(), 6); 3326 assert_eq!(tables[0], "blobentry"); 3327 assert_eq!(tables[1], "blobmetadata"); 3328 assert_eq!(tables[2], "grant"); 3329 assert_eq!(tables[3], "keyentry"); 3330 assert_eq!(tables[4], "keymetadata"); 3331 assert_eq!(tables[5], "keyparameter"); 3332 Ok(()) 3333 } 3334 3335 #[test] test_auth_token_table_invariant() -> Result<()>3336 fn test_auth_token_table_invariant() -> Result<()> { 3337 let mut db = new_test_db()?; 3338 let auth_token1 = HardwareAuthToken { 3339 challenge: i64::MAX, 3340 userId: 200, 3341 authenticatorId: 200, 3342 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0), 3343 timestamp: Timestamp { milliSeconds: 500 }, 3344 mac: String::from("mac").into_bytes(), 3345 }; 3346 db.insert_auth_token(&auth_token1); 3347 let auth_tokens_returned = get_auth_tokens(&db); 3348 assert_eq!(auth_tokens_returned.len(), 1); 3349 3350 // insert another auth token with the same values for the columns in the UNIQUE constraint 3351 // of the auth token table and different value for timestamp 3352 let auth_token2 = HardwareAuthToken { 3353 challenge: i64::MAX, 3354 userId: 200, 3355 authenticatorId: 200, 3356 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0), 3357 timestamp: Timestamp { milliSeconds: 600 }, 3358 mac: String::from("mac").into_bytes(), 3359 }; 3360 3361 db.insert_auth_token(&auth_token2); 3362 let mut auth_tokens_returned = get_auth_tokens(&db); 3363 assert_eq!(auth_tokens_returned.len(), 1); 3364 3365 if let Some(auth_token) = auth_tokens_returned.pop() { 3366 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600); 3367 } 3368 3369 // insert another auth token with the different values for the columns in the UNIQUE 3370 // constraint of the auth token table 3371 let auth_token3 = HardwareAuthToken { 3372 challenge: i64::MAX, 3373 userId: 201, 3374 authenticatorId: 200, 3375 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0), 3376 timestamp: Timestamp { milliSeconds: 600 }, 3377 mac: String::from("mac").into_bytes(), 3378 }; 3379 3380 db.insert_auth_token(&auth_token3); 3381 let auth_tokens_returned = get_auth_tokens(&db); 3382 assert_eq!(auth_tokens_returned.len(), 2); 3383 3384 Ok(()) 3385 } 3386 3387 // utility function for test_auth_token_table_invariant() get_auth_tokens(db: &KeystoreDB) -> Vec<AuthTokenEntry>3388 fn get_auth_tokens(db: &KeystoreDB) -> Vec<AuthTokenEntry> { 3389 db.perboot.get_all_auth_token_entries() 3390 } 3391 3392 #[test] test_persistence_for_files() -> Result<()>3393 fn test_persistence_for_files() -> Result<()> { 3394 let temp_dir = TempDir::new("persistent_db_test")?; 3395 let mut db = KeystoreDB::new(temp_dir.path(), None)?; 3396 3397 db.create_key_entry(&Domain::APP, &100, KeyType::Client, &KEYSTORE_UUID)?; 3398 let entries = get_keyentry(&db)?; 3399 assert_eq!(entries.len(), 1); 3400 3401 let db = KeystoreDB::new(temp_dir.path(), None)?; 3402 3403 let entries_new = get_keyentry(&db)?; 3404 assert_eq!(entries, entries_new); 3405 Ok(()) 3406 } 3407 3408 #[test] test_create_key_entry() -> Result<()>3409 fn test_create_key_entry() -> Result<()> { 3410 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>, Uuid) { 3411 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref(), ke.km_uuid.unwrap()) 3412 } 3413 3414 let mut db = new_test_db()?; 3415 3416 db.create_key_entry(&Domain::APP, &100, KeyType::Client, &KEYSTORE_UUID)?; 3417 db.create_key_entry(&Domain::SELINUX, &101, KeyType::Client, &KEYSTORE_UUID)?; 3418 3419 let entries = get_keyentry(&db)?; 3420 assert_eq!(entries.len(), 2); 3421 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None, KEYSTORE_UUID)); 3422 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None, KEYSTORE_UUID)); 3423 3424 // Test that we must pass in a valid Domain. 3425 check_result_is_error_containing_string( 3426 db.create_key_entry(&Domain::GRANT, &102, KeyType::Client, &KEYSTORE_UUID), 3427 "Domain Domain(1) must be either App or SELinux.", 3428 ); 3429 check_result_is_error_containing_string( 3430 db.create_key_entry(&Domain::BLOB, &103, KeyType::Client, &KEYSTORE_UUID), 3431 "Domain Domain(3) must be either App or SELinux.", 3432 ); 3433 check_result_is_error_containing_string( 3434 db.create_key_entry(&Domain::KEY_ID, &104, KeyType::Client, &KEYSTORE_UUID), 3435 "Domain Domain(4) must be either App or SELinux.", 3436 ); 3437 3438 Ok(()) 3439 } 3440 3441 #[test] test_add_unsigned_key() -> Result<()>3442 fn test_add_unsigned_key() -> Result<()> { 3443 let mut db = new_test_db()?; 3444 let public_key: Vec<u8> = vec![0x01, 0x02, 0x03]; 3445 let private_key: Vec<u8> = vec![0x04, 0x05, 0x06]; 3446 let raw_public_key: Vec<u8> = vec![0x07, 0x08, 0x09]; 3447 db.create_attestation_key_entry( 3448 &public_key, 3449 &raw_public_key, 3450 &private_key, 3451 &KEYSTORE_UUID, 3452 )?; 3453 let keys = db.fetch_unsigned_attestation_keys(5, &KEYSTORE_UUID)?; 3454 assert_eq!(keys.len(), 1); 3455 assert_eq!(keys[0], public_key); 3456 Ok(()) 3457 } 3458 3459 #[test] test_store_signed_attestation_certificate_chain() -> Result<()>3460 fn test_store_signed_attestation_certificate_chain() -> Result<()> { 3461 let mut db = new_test_db()?; 3462 let expiration_date: i64 = 20; 3463 let namespace: i64 = 30; 3464 let base_byte: u8 = 1; 3465 let loaded_values = 3466 load_attestation_key_pool(&mut db, expiration_date, namespace, base_byte)?; 3467 let chain = 3468 db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace, &KEYSTORE_UUID)?; 3469 assert_eq!(true, chain.is_some()); 3470 let cert_chain = chain.unwrap(); 3471 assert_eq!(cert_chain.private_key.to_vec(), loaded_values.priv_key); 3472 assert_eq!(cert_chain.batch_cert, loaded_values.batch_cert); 3473 assert_eq!(cert_chain.cert_chain, loaded_values.cert_chain); 3474 Ok(()) 3475 } 3476 3477 #[test] test_get_attestation_pool_status() -> Result<()>3478 fn test_get_attestation_pool_status() -> Result<()> { 3479 let mut db = new_test_db()?; 3480 let namespace: i64 = 30; 3481 load_attestation_key_pool( 3482 &mut db, 10, /* expiration */ 3483 namespace, 0x01, /* base_byte */ 3484 )?; 3485 load_attestation_key_pool(&mut db, 20 /* expiration */, namespace + 1, 0x02)?; 3486 load_attestation_key_pool(&mut db, 40 /* expiration */, namespace + 2, 0x03)?; 3487 let mut status = db.get_attestation_pool_status(9 /* expiration */, &KEYSTORE_UUID)?; 3488 assert_eq!(status.expiring, 0); 3489 assert_eq!(status.attested, 3); 3490 assert_eq!(status.unassigned, 0); 3491 assert_eq!(status.total, 3); 3492 assert_eq!( 3493 db.get_attestation_pool_status(15 /* expiration */, &KEYSTORE_UUID)?.expiring, 3494 1 3495 ); 3496 assert_eq!( 3497 db.get_attestation_pool_status(25 /* expiration */, &KEYSTORE_UUID)?.expiring, 3498 2 3499 ); 3500 assert_eq!( 3501 db.get_attestation_pool_status(60 /* expiration */, &KEYSTORE_UUID)?.expiring, 3502 3 3503 ); 3504 let public_key: Vec<u8> = vec![0x01, 0x02, 0x03]; 3505 let private_key: Vec<u8> = vec![0x04, 0x05, 0x06]; 3506 let raw_public_key: Vec<u8> = vec![0x07, 0x08, 0x09]; 3507 let cert_chain: Vec<u8> = vec![0x0a, 0x0b, 0x0c]; 3508 let batch_cert: Vec<u8> = vec![0x0d, 0x0e, 0x0f]; 3509 db.create_attestation_key_entry( 3510 &public_key, 3511 &raw_public_key, 3512 &private_key, 3513 &KEYSTORE_UUID, 3514 )?; 3515 status = db.get_attestation_pool_status(0 /* expiration */, &KEYSTORE_UUID)?; 3516 assert_eq!(status.attested, 3); 3517 assert_eq!(status.unassigned, 0); 3518 assert_eq!(status.total, 4); 3519 db.store_signed_attestation_certificate_chain( 3520 &raw_public_key, 3521 &batch_cert, 3522 &cert_chain, 3523 20, 3524 &KEYSTORE_UUID, 3525 )?; 3526 status = db.get_attestation_pool_status(0 /* expiration */, &KEYSTORE_UUID)?; 3527 assert_eq!(status.attested, 4); 3528 assert_eq!(status.unassigned, 1); 3529 assert_eq!(status.total, 4); 3530 Ok(()) 3531 } 3532 3533 #[test] test_remove_expired_certs() -> Result<()>3534 fn test_remove_expired_certs() -> Result<()> { 3535 let temp_dir = 3536 TempDir::new("test_remove_expired_certs_").expect("Failed to create temp dir."); 3537 let mut db = new_test_db_with_gc(temp_dir.path(), |_, _| Ok(()))?; 3538 let expiration_date: i64 = 3539 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64 + 10000; 3540 let namespace: i64 = 30; 3541 let namespace_del1: i64 = 45; 3542 let namespace_del2: i64 = 60; 3543 let entry_values = load_attestation_key_pool( 3544 &mut db, 3545 expiration_date, 3546 namespace, 3547 0x01, /* base_byte */ 3548 )?; 3549 load_attestation_key_pool(&mut db, 45, namespace_del1, 0x02)?; 3550 load_attestation_key_pool(&mut db, 60, namespace_del2, 0x03)?; 3551 3552 let blob_entry_row_count: u32 = db 3553 .conn 3554 .query_row("SELECT COUNT(id) FROM persistent.blobentry;", NO_PARAMS, |row| row.get(0)) 3555 .expect("Failed to get blob entry row count."); 3556 // We expect 9 rows here because there are three blobs per attestation key, i.e., 3557 // one key, one certificate chain, and one certificate. 3558 assert_eq!(blob_entry_row_count, 9); 3559 3560 assert_eq!(db.delete_expired_attestation_keys()?, 2); 3561 3562 let mut cert_chain = 3563 db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace, &KEYSTORE_UUID)?; 3564 assert!(cert_chain.is_some()); 3565 let value = cert_chain.unwrap(); 3566 assert_eq!(entry_values.batch_cert, value.batch_cert); 3567 assert_eq!(entry_values.cert_chain, value.cert_chain); 3568 assert_eq!(entry_values.priv_key, value.private_key.to_vec()); 3569 3570 cert_chain = db.retrieve_attestation_key_and_cert_chain( 3571 Domain::APP, 3572 namespace_del1, 3573 &KEYSTORE_UUID, 3574 )?; 3575 assert!(!cert_chain.is_some()); 3576 cert_chain = db.retrieve_attestation_key_and_cert_chain( 3577 Domain::APP, 3578 namespace_del2, 3579 &KEYSTORE_UUID, 3580 )?; 3581 assert!(!cert_chain.is_some()); 3582 3583 // Give the garbage collector half a second to catch up. 3584 std::thread::sleep(Duration::from_millis(500)); 3585 3586 let blob_entry_row_count: u32 = db 3587 .conn 3588 .query_row("SELECT COUNT(id) FROM persistent.blobentry;", NO_PARAMS, |row| row.get(0)) 3589 .expect("Failed to get blob entry row count."); 3590 // There shound be 3 blob entries left, because we deleted two of the attestation 3591 // key entries with three blobs each. 3592 assert_eq!(blob_entry_row_count, 3); 3593 3594 Ok(()) 3595 } 3596 3597 #[test] test_delete_all_attestation_keys() -> Result<()>3598 fn test_delete_all_attestation_keys() -> Result<()> { 3599 let mut db = new_test_db()?; 3600 load_attestation_key_pool(&mut db, 45 /* expiration */, 1 /* namespace */, 0x02)?; 3601 load_attestation_key_pool(&mut db, 80 /* expiration */, 2 /* namespace */, 0x03)?; 3602 db.create_key_entry(&Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?; 3603 let result = db.delete_all_attestation_keys()?; 3604 3605 // Give the garbage collector half a second to catch up. 3606 std::thread::sleep(Duration::from_millis(500)); 3607 3608 // Attestation keys should be deleted, and the regular key should remain. 3609 assert_eq!(result, 2); 3610 3611 Ok(()) 3612 } 3613 3614 #[test] test_rebind_alias() -> Result<()>3615 fn test_rebind_alias() -> Result<()> { 3616 fn extractor( 3617 ke: &KeyEntryRow, 3618 ) -> (Option<Domain>, Option<i64>, Option<&str>, Option<Uuid>) { 3619 (ke.domain, ke.namespace, ke.alias.as_deref(), ke.km_uuid) 3620 } 3621 3622 let mut db = new_test_db()?; 3623 db.create_key_entry(&Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?; 3624 db.create_key_entry(&Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?; 3625 let entries = get_keyentry(&db)?; 3626 assert_eq!(entries.len(), 2); 3627 assert_eq!( 3628 extractor(&entries[0]), 3629 (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID)) 3630 ); 3631 assert_eq!( 3632 extractor(&entries[1]), 3633 (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID)) 3634 ); 3635 3636 // Test that the first call to rebind_alias sets the alias. 3637 rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?; 3638 let entries = get_keyentry(&db)?; 3639 assert_eq!(entries.len(), 2); 3640 assert_eq!( 3641 extractor(&entries[0]), 3642 (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID)) 3643 ); 3644 assert_eq!( 3645 extractor(&entries[1]), 3646 (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID)) 3647 ); 3648 3649 // Test that the second call to rebind_alias also empties the old one. 3650 rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?; 3651 let entries = get_keyentry(&db)?; 3652 assert_eq!(entries.len(), 2); 3653 assert_eq!(extractor(&entries[0]), (None, None, None, Some(KEYSTORE_UUID))); 3654 assert_eq!( 3655 extractor(&entries[1]), 3656 (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID)) 3657 ); 3658 3659 // Test that we must pass in a valid Domain. 3660 check_result_is_error_containing_string( 3661 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42), 3662 "Domain Domain(1) must be either App or SELinux.", 3663 ); 3664 check_result_is_error_containing_string( 3665 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42), 3666 "Domain Domain(3) must be either App or SELinux.", 3667 ); 3668 check_result_is_error_containing_string( 3669 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42), 3670 "Domain Domain(4) must be either App or SELinux.", 3671 ); 3672 3673 // Test that we correctly handle setting an alias for something that does not exist. 3674 check_result_is_error_containing_string( 3675 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42), 3676 "Expected to update a single entry but instead updated 0", 3677 ); 3678 // Test that we correctly abort the transaction in this case. 3679 let entries = get_keyentry(&db)?; 3680 assert_eq!(entries.len(), 2); 3681 assert_eq!(extractor(&entries[0]), (None, None, None, Some(KEYSTORE_UUID))); 3682 assert_eq!( 3683 extractor(&entries[1]), 3684 (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID)) 3685 ); 3686 3687 Ok(()) 3688 } 3689 3690 #[test] test_grant_ungrant() -> Result<()>3691 fn test_grant_ungrant() -> Result<()> { 3692 const CALLER_UID: u32 = 15; 3693 const GRANTEE_UID: u32 = 12; 3694 const SELINUX_NAMESPACE: i64 = 7; 3695 3696 let mut db = new_test_db()?; 3697 db.conn.execute( 3698 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state, km_uuid) 3699 VALUES (1, 0, 0, 15, 'key', 1, ?), (2, 0, 2, 7, 'yek', 1, ?);", 3700 params![KEYSTORE_UUID, KEYSTORE_UUID], 3701 )?; 3702 let app_key = KeyDescriptor { 3703 domain: super::Domain::APP, 3704 nspace: 0, 3705 alias: Some("key".to_string()), 3706 blob: None, 3707 }; 3708 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()]; 3709 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()]; 3710 3711 // Reset totally predictable random number generator in case we 3712 // are not the first test running on this thread. 3713 reset_random(); 3714 let next_random = 0i64; 3715 3716 let app_granted_key = db 3717 .grant(&app_key, CALLER_UID, GRANTEE_UID, PVEC1, |k, a| { 3718 assert_eq!(*a, PVEC1); 3719 assert_eq!( 3720 *k, 3721 KeyDescriptor { 3722 domain: super::Domain::APP, 3723 // namespace must be set to the caller_uid. 3724 nspace: CALLER_UID as i64, 3725 alias: Some("key".to_string()), 3726 blob: None, 3727 } 3728 ); 3729 Ok(()) 3730 }) 3731 .unwrap(); 3732 3733 assert_eq!( 3734 app_granted_key, 3735 KeyDescriptor { 3736 domain: super::Domain::GRANT, 3737 // The grantid is next_random due to the mock random number generator. 3738 nspace: next_random, 3739 alias: None, 3740 blob: None, 3741 } 3742 ); 3743 3744 let selinux_key = KeyDescriptor { 3745 domain: super::Domain::SELINUX, 3746 nspace: SELINUX_NAMESPACE, 3747 alias: Some("yek".to_string()), 3748 blob: None, 3749 }; 3750 3751 let selinux_granted_key = db 3752 .grant(&selinux_key, CALLER_UID, 12, PVEC1, |k, a| { 3753 assert_eq!(*a, PVEC1); 3754 assert_eq!( 3755 *k, 3756 KeyDescriptor { 3757 domain: super::Domain::SELINUX, 3758 // namespace must be the supplied SELinux 3759 // namespace. 3760 nspace: SELINUX_NAMESPACE, 3761 alias: Some("yek".to_string()), 3762 blob: None, 3763 } 3764 ); 3765 Ok(()) 3766 }) 3767 .unwrap(); 3768 3769 assert_eq!( 3770 selinux_granted_key, 3771 KeyDescriptor { 3772 domain: super::Domain::GRANT, 3773 // The grantid is next_random + 1 due to the mock random number generator. 3774 nspace: next_random + 1, 3775 alias: None, 3776 blob: None, 3777 } 3778 ); 3779 3780 // This should update the existing grant with PVEC2. 3781 let selinux_granted_key = db 3782 .grant(&selinux_key, CALLER_UID, 12, PVEC2, |k, a| { 3783 assert_eq!(*a, PVEC2); 3784 assert_eq!( 3785 *k, 3786 KeyDescriptor { 3787 domain: super::Domain::SELINUX, 3788 // namespace must be the supplied SELinux 3789 // namespace. 3790 nspace: SELINUX_NAMESPACE, 3791 alias: Some("yek".to_string()), 3792 blob: None, 3793 } 3794 ); 3795 Ok(()) 3796 }) 3797 .unwrap(); 3798 3799 assert_eq!( 3800 selinux_granted_key, 3801 KeyDescriptor { 3802 domain: super::Domain::GRANT, 3803 // Same grant id as before. The entry was only updated. 3804 nspace: next_random + 1, 3805 alias: None, 3806 blob: None, 3807 } 3808 ); 3809 3810 { 3811 // Limiting scope of stmt, because it borrows db. 3812 let mut stmt = db 3813 .conn 3814 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?; 3815 let mut rows = 3816 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| { 3817 Ok(( 3818 row.get(0)?, 3819 row.get(1)?, 3820 row.get(2)?, 3821 KeyPermSet::from(row.get::<_, i32>(3)?), 3822 )) 3823 })?; 3824 3825 let r = rows.next().unwrap().unwrap(); 3826 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1)); 3827 let r = rows.next().unwrap().unwrap(); 3828 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2)); 3829 assert!(rows.next().is_none()); 3830 } 3831 3832 debug_dump_keyentry_table(&mut db)?; 3833 println!("app_key {:?}", app_key); 3834 println!("selinux_key {:?}", selinux_key); 3835 3836 db.ungrant(&app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?; 3837 db.ungrant(&selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?; 3838 3839 Ok(()) 3840 } 3841 3842 static TEST_KEY_BLOB: &[u8] = b"my test blob"; 3843 static TEST_CERT_BLOB: &[u8] = b"my test cert"; 3844 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain"; 3845 3846 #[test] test_set_blob() -> Result<()>3847 fn test_set_blob() -> Result<()> { 3848 let key_id = KEY_ID_LOCK.get(3000); 3849 let mut db = new_test_db()?; 3850 let mut blob_metadata = BlobMetaData::new(); 3851 blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID)); 3852 db.set_blob( 3853 &key_id, 3854 SubComponentType::KEY_BLOB, 3855 Some(TEST_KEY_BLOB), 3856 Some(&blob_metadata), 3857 )?; 3858 db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB), None)?; 3859 db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB), None)?; 3860 drop(key_id); 3861 3862 let mut stmt = db.conn.prepare( 3863 "SELECT subcomponent_type, keyentryid, blob, id FROM persistent.blobentry 3864 ORDER BY subcomponent_type ASC;", 3865 )?; 3866 let mut rows = stmt 3867 .query_map::<((SubComponentType, i64, Vec<u8>), i64), _, _>(NO_PARAMS, |row| { 3868 Ok(((row.get(0)?, row.get(1)?, row.get(2)?), row.get(3)?)) 3869 })?; 3870 let (r, id) = rows.next().unwrap().unwrap(); 3871 assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec())); 3872 let (r, _) = rows.next().unwrap().unwrap(); 3873 assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec())); 3874 let (r, _) = rows.next().unwrap().unwrap(); 3875 assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec())); 3876 3877 drop(rows); 3878 drop(stmt); 3879 3880 assert_eq!( 3881 db.with_transaction(TransactionBehavior::Immediate, |tx| { 3882 BlobMetaData::load_from_db(id, tx).no_gc() 3883 }) 3884 .expect("Should find blob metadata."), 3885 blob_metadata 3886 ); 3887 Ok(()) 3888 } 3889 3890 static TEST_ALIAS: &str = "my super duper key"; 3891 3892 #[test] test_insert_and_load_full_keyentry_domain_app() -> Result<()>3893 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> { 3894 let mut db = new_test_db()?; 3895 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None) 3896 .context("test_insert_and_load_full_keyentry_domain_app")? 3897 .0; 3898 let (_key_guard, key_entry) = db 3899 .load_key_entry( 3900 &KeyDescriptor { 3901 domain: Domain::APP, 3902 nspace: 0, 3903 alias: Some(TEST_ALIAS.to_string()), 3904 blob: None, 3905 }, 3906 KeyType::Client, 3907 KeyEntryLoadBits::BOTH, 3908 1, 3909 |_k, _av| Ok(()), 3910 ) 3911 .unwrap(); 3912 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 3913 3914 db.unbind_key( 3915 &KeyDescriptor { 3916 domain: Domain::APP, 3917 nspace: 0, 3918 alias: Some(TEST_ALIAS.to_string()), 3919 blob: None, 3920 }, 3921 KeyType::Client, 3922 1, 3923 |_, _| Ok(()), 3924 ) 3925 .unwrap(); 3926 3927 assert_eq!( 3928 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 3929 db.load_key_entry( 3930 &KeyDescriptor { 3931 domain: Domain::APP, 3932 nspace: 0, 3933 alias: Some(TEST_ALIAS.to_string()), 3934 blob: None, 3935 }, 3936 KeyType::Client, 3937 KeyEntryLoadBits::NONE, 3938 1, 3939 |_k, _av| Ok(()), 3940 ) 3941 .unwrap_err() 3942 .root_cause() 3943 .downcast_ref::<KsError>() 3944 ); 3945 3946 Ok(()) 3947 } 3948 3949 #[test] test_insert_and_load_certificate_entry_domain_app() -> Result<()>3950 fn test_insert_and_load_certificate_entry_domain_app() -> Result<()> { 3951 let mut db = new_test_db()?; 3952 3953 db.store_new_certificate( 3954 &KeyDescriptor { 3955 domain: Domain::APP, 3956 nspace: 1, 3957 alias: Some(TEST_ALIAS.to_string()), 3958 blob: None, 3959 }, 3960 KeyType::Client, 3961 TEST_CERT_BLOB, 3962 &KEYSTORE_UUID, 3963 ) 3964 .expect("Trying to insert cert."); 3965 3966 let (_key_guard, mut key_entry) = db 3967 .load_key_entry( 3968 &KeyDescriptor { 3969 domain: Domain::APP, 3970 nspace: 1, 3971 alias: Some(TEST_ALIAS.to_string()), 3972 blob: None, 3973 }, 3974 KeyType::Client, 3975 KeyEntryLoadBits::PUBLIC, 3976 1, 3977 |_k, _av| Ok(()), 3978 ) 3979 .expect("Trying to read certificate entry."); 3980 3981 assert!(key_entry.pure_cert()); 3982 assert!(key_entry.cert().is_none()); 3983 assert_eq!(key_entry.take_cert_chain(), Some(TEST_CERT_BLOB.to_vec())); 3984 3985 db.unbind_key( 3986 &KeyDescriptor { 3987 domain: Domain::APP, 3988 nspace: 1, 3989 alias: Some(TEST_ALIAS.to_string()), 3990 blob: None, 3991 }, 3992 KeyType::Client, 3993 1, 3994 |_, _| Ok(()), 3995 ) 3996 .unwrap(); 3997 3998 assert_eq!( 3999 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4000 db.load_key_entry( 4001 &KeyDescriptor { 4002 domain: Domain::APP, 4003 nspace: 1, 4004 alias: Some(TEST_ALIAS.to_string()), 4005 blob: None, 4006 }, 4007 KeyType::Client, 4008 KeyEntryLoadBits::NONE, 4009 1, 4010 |_k, _av| Ok(()), 4011 ) 4012 .unwrap_err() 4013 .root_cause() 4014 .downcast_ref::<KsError>() 4015 ); 4016 4017 Ok(()) 4018 } 4019 4020 #[test] test_insert_and_load_full_keyentry_domain_selinux() -> Result<()>4021 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> { 4022 let mut db = new_test_db()?; 4023 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, None) 4024 .context("test_insert_and_load_full_keyentry_domain_selinux")? 4025 .0; 4026 let (_key_guard, key_entry) = db 4027 .load_key_entry( 4028 &KeyDescriptor { 4029 domain: Domain::SELINUX, 4030 nspace: 1, 4031 alias: Some(TEST_ALIAS.to_string()), 4032 blob: None, 4033 }, 4034 KeyType::Client, 4035 KeyEntryLoadBits::BOTH, 4036 1, 4037 |_k, _av| Ok(()), 4038 ) 4039 .unwrap(); 4040 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4041 4042 db.unbind_key( 4043 &KeyDescriptor { 4044 domain: Domain::SELINUX, 4045 nspace: 1, 4046 alias: Some(TEST_ALIAS.to_string()), 4047 blob: None, 4048 }, 4049 KeyType::Client, 4050 1, 4051 |_, _| Ok(()), 4052 ) 4053 .unwrap(); 4054 4055 assert_eq!( 4056 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4057 db.load_key_entry( 4058 &KeyDescriptor { 4059 domain: Domain::SELINUX, 4060 nspace: 1, 4061 alias: Some(TEST_ALIAS.to_string()), 4062 blob: None, 4063 }, 4064 KeyType::Client, 4065 KeyEntryLoadBits::NONE, 4066 1, 4067 |_k, _av| Ok(()), 4068 ) 4069 .unwrap_err() 4070 .root_cause() 4071 .downcast_ref::<KsError>() 4072 ); 4073 4074 Ok(()) 4075 } 4076 4077 #[test] test_insert_and_load_full_keyentry_domain_key_id() -> Result<()>4078 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> { 4079 let mut db = new_test_db()?; 4080 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, None) 4081 .context("test_insert_and_load_full_keyentry_domain_key_id")? 4082 .0; 4083 let (_, key_entry) = db 4084 .load_key_entry( 4085 &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None }, 4086 KeyType::Client, 4087 KeyEntryLoadBits::BOTH, 4088 1, 4089 |_k, _av| Ok(()), 4090 ) 4091 .unwrap(); 4092 4093 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4094 4095 db.unbind_key( 4096 &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None }, 4097 KeyType::Client, 4098 1, 4099 |_, _| Ok(()), 4100 ) 4101 .unwrap(); 4102 4103 assert_eq!( 4104 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4105 db.load_key_entry( 4106 &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None }, 4107 KeyType::Client, 4108 KeyEntryLoadBits::NONE, 4109 1, 4110 |_k, _av| Ok(()), 4111 ) 4112 .unwrap_err() 4113 .root_cause() 4114 .downcast_ref::<KsError>() 4115 ); 4116 4117 Ok(()) 4118 } 4119 4120 #[test] test_check_and_update_key_usage_count_with_limited_use_key() -> Result<()>4121 fn test_check_and_update_key_usage_count_with_limited_use_key() -> Result<()> { 4122 let mut db = new_test_db()?; 4123 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, Some(123)) 4124 .context("test_check_and_update_key_usage_count_with_limited_use_key")? 4125 .0; 4126 // Update the usage count of the limited use key. 4127 db.check_and_update_key_usage_count(key_id)?; 4128 4129 let (_key_guard, key_entry) = db.load_key_entry( 4130 &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None }, 4131 KeyType::Client, 4132 KeyEntryLoadBits::BOTH, 4133 1, 4134 |_k, _av| Ok(()), 4135 )?; 4136 4137 // The usage count is decremented now. 4138 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, Some(122))); 4139 4140 Ok(()) 4141 } 4142 4143 #[test] test_check_and_update_key_usage_count_with_exhausted_limited_use_key() -> Result<()>4144 fn test_check_and_update_key_usage_count_with_exhausted_limited_use_key() -> Result<()> { 4145 let mut db = new_test_db()?; 4146 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, Some(1)) 4147 .context("test_check_and_update_key_usage_count_with_exhausted_limited_use_key")? 4148 .0; 4149 // Update the usage count of the limited use key. 4150 db.check_and_update_key_usage_count(key_id).expect(concat!( 4151 "In test_check_and_update_key_usage_count_with_exhausted_limited_use_key: ", 4152 "This should succeed." 4153 )); 4154 4155 // Try to update the exhausted limited use key. 4156 let e = db.check_and_update_key_usage_count(key_id).expect_err(concat!( 4157 "In test_check_and_update_key_usage_count_with_exhausted_limited_use_key: ", 4158 "This should fail." 4159 )); 4160 assert_eq!( 4161 &KsError::Km(ErrorCode::INVALID_KEY_BLOB), 4162 e.root_cause().downcast_ref::<KsError>().unwrap() 4163 ); 4164 4165 Ok(()) 4166 } 4167 4168 #[test] test_insert_and_load_full_keyentry_from_grant() -> Result<()>4169 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> { 4170 let mut db = new_test_db()?; 4171 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None) 4172 .context("test_insert_and_load_full_keyentry_from_grant")? 4173 .0; 4174 4175 let granted_key = db 4176 .grant( 4177 &KeyDescriptor { 4178 domain: Domain::APP, 4179 nspace: 0, 4180 alias: Some(TEST_ALIAS.to_string()), 4181 blob: None, 4182 }, 4183 1, 4184 2, 4185 key_perm_set![KeyPerm::use_()], 4186 |_k, _av| Ok(()), 4187 ) 4188 .unwrap(); 4189 4190 debug_dump_grant_table(&mut db)?; 4191 4192 let (_key_guard, key_entry) = db 4193 .load_key_entry(&granted_key, KeyType::Client, KeyEntryLoadBits::BOTH, 2, |k, av| { 4194 assert_eq!(Domain::GRANT, k.domain); 4195 assert!(av.unwrap().includes(KeyPerm::use_())); 4196 Ok(()) 4197 }) 4198 .unwrap(); 4199 4200 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4201 4202 db.unbind_key(&granted_key, KeyType::Client, 2, |_, _| Ok(())).unwrap(); 4203 4204 assert_eq!( 4205 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4206 db.load_key_entry( 4207 &granted_key, 4208 KeyType::Client, 4209 KeyEntryLoadBits::NONE, 4210 2, 4211 |_k, _av| Ok(()), 4212 ) 4213 .unwrap_err() 4214 .root_cause() 4215 .downcast_ref::<KsError>() 4216 ); 4217 4218 Ok(()) 4219 } 4220 4221 // This test attempts to load a key by key id while the caller is not the owner 4222 // but a grant exists for the given key and the caller. 4223 #[test] test_insert_and_load_full_keyentry_from_grant_by_key_id() -> Result<()>4224 fn test_insert_and_load_full_keyentry_from_grant_by_key_id() -> Result<()> { 4225 let mut db = new_test_db()?; 4226 const OWNER_UID: u32 = 1u32; 4227 const GRANTEE_UID: u32 = 2u32; 4228 const SOMEONE_ELSE_UID: u32 = 3u32; 4229 let key_id = make_test_key_entry(&mut db, Domain::APP, OWNER_UID as i64, TEST_ALIAS, None) 4230 .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")? 4231 .0; 4232 4233 db.grant( 4234 &KeyDescriptor { 4235 domain: Domain::APP, 4236 nspace: 0, 4237 alias: Some(TEST_ALIAS.to_string()), 4238 blob: None, 4239 }, 4240 OWNER_UID, 4241 GRANTEE_UID, 4242 key_perm_set![KeyPerm::use_()], 4243 |_k, _av| Ok(()), 4244 ) 4245 .unwrap(); 4246 4247 debug_dump_grant_table(&mut db)?; 4248 4249 let id_descriptor = 4250 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, ..Default::default() }; 4251 4252 let (_, key_entry) = db 4253 .load_key_entry( 4254 &id_descriptor, 4255 KeyType::Client, 4256 KeyEntryLoadBits::BOTH, 4257 GRANTEE_UID, 4258 |k, av| { 4259 assert_eq!(Domain::APP, k.domain); 4260 assert_eq!(OWNER_UID as i64, k.nspace); 4261 assert!(av.unwrap().includes(KeyPerm::use_())); 4262 Ok(()) 4263 }, 4264 ) 4265 .unwrap(); 4266 4267 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4268 4269 let (_, key_entry) = db 4270 .load_key_entry( 4271 &id_descriptor, 4272 KeyType::Client, 4273 KeyEntryLoadBits::BOTH, 4274 SOMEONE_ELSE_UID, 4275 |k, av| { 4276 assert_eq!(Domain::APP, k.domain); 4277 assert_eq!(OWNER_UID as i64, k.nspace); 4278 assert!(av.is_none()); 4279 Ok(()) 4280 }, 4281 ) 4282 .unwrap(); 4283 4284 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4285 4286 db.unbind_key(&id_descriptor, KeyType::Client, OWNER_UID, |_, _| Ok(())).unwrap(); 4287 4288 assert_eq!( 4289 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4290 db.load_key_entry( 4291 &id_descriptor, 4292 KeyType::Client, 4293 KeyEntryLoadBits::NONE, 4294 GRANTEE_UID, 4295 |_k, _av| Ok(()), 4296 ) 4297 .unwrap_err() 4298 .root_cause() 4299 .downcast_ref::<KsError>() 4300 ); 4301 4302 Ok(()) 4303 } 4304 4305 // Creates a key migrates it to a different location and then tries to access it by the old 4306 // and new location. 4307 #[test] test_migrate_key_app_to_app() -> Result<()>4308 fn test_migrate_key_app_to_app() -> Result<()> { 4309 let mut db = new_test_db()?; 4310 const SOURCE_UID: u32 = 1u32; 4311 const DESTINATION_UID: u32 = 2u32; 4312 static SOURCE_ALIAS: &str = &"SOURCE_ALIAS"; 4313 static DESTINATION_ALIAS: &str = &"DESTINATION_ALIAS"; 4314 let key_id_guard = 4315 make_test_key_entry(&mut db, Domain::APP, SOURCE_UID as i64, SOURCE_ALIAS, None) 4316 .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?; 4317 4318 let source_descriptor: KeyDescriptor = KeyDescriptor { 4319 domain: Domain::APP, 4320 nspace: -1, 4321 alias: Some(SOURCE_ALIAS.to_string()), 4322 blob: None, 4323 }; 4324 4325 let destination_descriptor: KeyDescriptor = KeyDescriptor { 4326 domain: Domain::APP, 4327 nspace: -1, 4328 alias: Some(DESTINATION_ALIAS.to_string()), 4329 blob: None, 4330 }; 4331 4332 let key_id = key_id_guard.id(); 4333 4334 db.migrate_key_namespace(key_id_guard, &destination_descriptor, DESTINATION_UID, |_k| { 4335 Ok(()) 4336 }) 4337 .unwrap(); 4338 4339 let (_, key_entry) = db 4340 .load_key_entry( 4341 &destination_descriptor, 4342 KeyType::Client, 4343 KeyEntryLoadBits::BOTH, 4344 DESTINATION_UID, 4345 |k, av| { 4346 assert_eq!(Domain::APP, k.domain); 4347 assert_eq!(DESTINATION_UID as i64, k.nspace); 4348 assert!(av.is_none()); 4349 Ok(()) 4350 }, 4351 ) 4352 .unwrap(); 4353 4354 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4355 4356 assert_eq!( 4357 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4358 db.load_key_entry( 4359 &source_descriptor, 4360 KeyType::Client, 4361 KeyEntryLoadBits::NONE, 4362 SOURCE_UID, 4363 |_k, _av| Ok(()), 4364 ) 4365 .unwrap_err() 4366 .root_cause() 4367 .downcast_ref::<KsError>() 4368 ); 4369 4370 Ok(()) 4371 } 4372 4373 // Creates a key migrates it to a different location and then tries to access it by the old 4374 // and new location. 4375 #[test] test_migrate_key_app_to_selinux() -> Result<()>4376 fn test_migrate_key_app_to_selinux() -> Result<()> { 4377 let mut db = new_test_db()?; 4378 const SOURCE_UID: u32 = 1u32; 4379 const DESTINATION_UID: u32 = 2u32; 4380 const DESTINATION_NAMESPACE: i64 = 1000i64; 4381 static SOURCE_ALIAS: &str = &"SOURCE_ALIAS"; 4382 static DESTINATION_ALIAS: &str = &"DESTINATION_ALIAS"; 4383 let key_id_guard = 4384 make_test_key_entry(&mut db, Domain::APP, SOURCE_UID as i64, SOURCE_ALIAS, None) 4385 .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?; 4386 4387 let source_descriptor: KeyDescriptor = KeyDescriptor { 4388 domain: Domain::APP, 4389 nspace: -1, 4390 alias: Some(SOURCE_ALIAS.to_string()), 4391 blob: None, 4392 }; 4393 4394 let destination_descriptor: KeyDescriptor = KeyDescriptor { 4395 domain: Domain::SELINUX, 4396 nspace: DESTINATION_NAMESPACE, 4397 alias: Some(DESTINATION_ALIAS.to_string()), 4398 blob: None, 4399 }; 4400 4401 let key_id = key_id_guard.id(); 4402 4403 db.migrate_key_namespace(key_id_guard, &destination_descriptor, DESTINATION_UID, |_k| { 4404 Ok(()) 4405 }) 4406 .unwrap(); 4407 4408 let (_, key_entry) = db 4409 .load_key_entry( 4410 &destination_descriptor, 4411 KeyType::Client, 4412 KeyEntryLoadBits::BOTH, 4413 DESTINATION_UID, 4414 |k, av| { 4415 assert_eq!(Domain::SELINUX, k.domain); 4416 assert_eq!(DESTINATION_NAMESPACE as i64, k.nspace); 4417 assert!(av.is_none()); 4418 Ok(()) 4419 }, 4420 ) 4421 .unwrap(); 4422 4423 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4424 4425 assert_eq!( 4426 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4427 db.load_key_entry( 4428 &source_descriptor, 4429 KeyType::Client, 4430 KeyEntryLoadBits::NONE, 4431 SOURCE_UID, 4432 |_k, _av| Ok(()), 4433 ) 4434 .unwrap_err() 4435 .root_cause() 4436 .downcast_ref::<KsError>() 4437 ); 4438 4439 Ok(()) 4440 } 4441 4442 // Creates two keys and tries to migrate the first to the location of the second which 4443 // is expected to fail. 4444 #[test] test_migrate_key_destination_occupied() -> Result<()>4445 fn test_migrate_key_destination_occupied() -> Result<()> { 4446 let mut db = new_test_db()?; 4447 const SOURCE_UID: u32 = 1u32; 4448 const DESTINATION_UID: u32 = 2u32; 4449 static SOURCE_ALIAS: &str = &"SOURCE_ALIAS"; 4450 static DESTINATION_ALIAS: &str = &"DESTINATION_ALIAS"; 4451 let key_id_guard = 4452 make_test_key_entry(&mut db, Domain::APP, SOURCE_UID as i64, SOURCE_ALIAS, None) 4453 .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?; 4454 make_test_key_entry(&mut db, Domain::APP, DESTINATION_UID as i64, DESTINATION_ALIAS, None) 4455 .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?; 4456 4457 let destination_descriptor: KeyDescriptor = KeyDescriptor { 4458 domain: Domain::APP, 4459 nspace: -1, 4460 alias: Some(DESTINATION_ALIAS.to_string()), 4461 blob: None, 4462 }; 4463 4464 assert_eq!( 4465 Some(&KsError::Rc(ResponseCode::INVALID_ARGUMENT)), 4466 db.migrate_key_namespace( 4467 key_id_guard, 4468 &destination_descriptor, 4469 DESTINATION_UID, 4470 |_k| Ok(()) 4471 ) 4472 .unwrap_err() 4473 .root_cause() 4474 .downcast_ref::<KsError>() 4475 ); 4476 4477 Ok(()) 4478 } 4479 4480 #[test] test_upgrade_0_to_1()4481 fn test_upgrade_0_to_1() { 4482 const ALIAS1: &str = &"test_upgrade_0_to_1_1"; 4483 const ALIAS2: &str = &"test_upgrade_0_to_1_2"; 4484 const ALIAS3: &str = &"test_upgrade_0_to_1_3"; 4485 const UID: u32 = 33; 4486 let temp_dir = Arc::new(TempDir::new("test_upgrade_0_to_1").unwrap()); 4487 let mut db = KeystoreDB::new(temp_dir.path(), None).unwrap(); 4488 let key_id_untouched1 = 4489 make_test_key_entry(&mut db, Domain::APP, UID as i64, ALIAS1, None).unwrap().id(); 4490 let key_id_untouched2 = 4491 make_bootlevel_key_entry(&mut db, Domain::APP, UID as i64, ALIAS2, false).unwrap().id(); 4492 let key_id_deleted = 4493 make_bootlevel_key_entry(&mut db, Domain::APP, UID as i64, ALIAS3, true).unwrap().id(); 4494 4495 let (_, key_entry) = db 4496 .load_key_entry( 4497 &KeyDescriptor { 4498 domain: Domain::APP, 4499 nspace: -1, 4500 alias: Some(ALIAS1.to_string()), 4501 blob: None, 4502 }, 4503 KeyType::Client, 4504 KeyEntryLoadBits::BOTH, 4505 UID, 4506 |k, av| { 4507 assert_eq!(Domain::APP, k.domain); 4508 assert_eq!(UID as i64, k.nspace); 4509 assert!(av.is_none()); 4510 Ok(()) 4511 }, 4512 ) 4513 .unwrap(); 4514 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id_untouched1, None)); 4515 let (_, key_entry) = db 4516 .load_key_entry( 4517 &KeyDescriptor { 4518 domain: Domain::APP, 4519 nspace: -1, 4520 alias: Some(ALIAS2.to_string()), 4521 blob: None, 4522 }, 4523 KeyType::Client, 4524 KeyEntryLoadBits::BOTH, 4525 UID, 4526 |k, av| { 4527 assert_eq!(Domain::APP, k.domain); 4528 assert_eq!(UID as i64, k.nspace); 4529 assert!(av.is_none()); 4530 Ok(()) 4531 }, 4532 ) 4533 .unwrap(); 4534 assert_eq!(key_entry, make_bootlevel_test_key_entry_test_vector(key_id_untouched2, false)); 4535 let (_, key_entry) = db 4536 .load_key_entry( 4537 &KeyDescriptor { 4538 domain: Domain::APP, 4539 nspace: -1, 4540 alias: Some(ALIAS3.to_string()), 4541 blob: None, 4542 }, 4543 KeyType::Client, 4544 KeyEntryLoadBits::BOTH, 4545 UID, 4546 |k, av| { 4547 assert_eq!(Domain::APP, k.domain); 4548 assert_eq!(UID as i64, k.nspace); 4549 assert!(av.is_none()); 4550 Ok(()) 4551 }, 4552 ) 4553 .unwrap(); 4554 assert_eq!(key_entry, make_bootlevel_test_key_entry_test_vector(key_id_deleted, true)); 4555 4556 db.with_transaction(TransactionBehavior::Immediate, |tx| { 4557 KeystoreDB::from_0_to_1(tx).no_gc() 4558 }) 4559 .unwrap(); 4560 4561 let (_, key_entry) = db 4562 .load_key_entry( 4563 &KeyDescriptor { 4564 domain: Domain::APP, 4565 nspace: -1, 4566 alias: Some(ALIAS1.to_string()), 4567 blob: None, 4568 }, 4569 KeyType::Client, 4570 KeyEntryLoadBits::BOTH, 4571 UID, 4572 |k, av| { 4573 assert_eq!(Domain::APP, k.domain); 4574 assert_eq!(UID as i64, k.nspace); 4575 assert!(av.is_none()); 4576 Ok(()) 4577 }, 4578 ) 4579 .unwrap(); 4580 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id_untouched1, None)); 4581 let (_, key_entry) = db 4582 .load_key_entry( 4583 &KeyDescriptor { 4584 domain: Domain::APP, 4585 nspace: -1, 4586 alias: Some(ALIAS2.to_string()), 4587 blob: None, 4588 }, 4589 KeyType::Client, 4590 KeyEntryLoadBits::BOTH, 4591 UID, 4592 |k, av| { 4593 assert_eq!(Domain::APP, k.domain); 4594 assert_eq!(UID as i64, k.nspace); 4595 assert!(av.is_none()); 4596 Ok(()) 4597 }, 4598 ) 4599 .unwrap(); 4600 assert_eq!(key_entry, make_bootlevel_test_key_entry_test_vector(key_id_untouched2, false)); 4601 assert_eq!( 4602 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)), 4603 db.load_key_entry( 4604 &KeyDescriptor { 4605 domain: Domain::APP, 4606 nspace: -1, 4607 alias: Some(ALIAS3.to_string()), 4608 blob: None, 4609 }, 4610 KeyType::Client, 4611 KeyEntryLoadBits::BOTH, 4612 UID, 4613 |k, av| { 4614 assert_eq!(Domain::APP, k.domain); 4615 assert_eq!(UID as i64, k.nspace); 4616 assert!(av.is_none()); 4617 Ok(()) 4618 }, 4619 ) 4620 .unwrap_err() 4621 .root_cause() 4622 .downcast_ref::<KsError>() 4623 ); 4624 } 4625 4626 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key"; 4627 4628 #[test] test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()>4629 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> { 4630 let handle = { 4631 let temp_dir = Arc::new(TempDir::new("id_lock_test")?); 4632 let temp_dir_clone = temp_dir.clone(); 4633 let mut db = KeystoreDB::new(temp_dir.path(), None)?; 4634 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS, None) 4635 .context("test_insert_and_load_full_keyentry_domain_app")? 4636 .0; 4637 let (_key_guard, key_entry) = db 4638 .load_key_entry( 4639 &KeyDescriptor { 4640 domain: Domain::APP, 4641 nspace: 0, 4642 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()), 4643 blob: None, 4644 }, 4645 KeyType::Client, 4646 KeyEntryLoadBits::BOTH, 4647 33, 4648 |_k, _av| Ok(()), 4649 ) 4650 .unwrap(); 4651 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None)); 4652 let state = Arc::new(AtomicU8::new(1)); 4653 let state2 = state.clone(); 4654 4655 // Spawning a second thread that attempts to acquire the key id lock 4656 // for the same key as the primary thread. The primary thread then 4657 // waits, thereby forcing the secondary thread into the second stage 4658 // of acquiring the lock (see KEY ID LOCK 2/2 above). 4659 // The test succeeds if the secondary thread observes the transition 4660 // of `state` from 1 to 2, despite having a whole second to overtake 4661 // the primary thread. 4662 let handle = thread::spawn(move || { 4663 let temp_dir = temp_dir_clone; 4664 let mut db = KeystoreDB::new(temp_dir.path(), None).unwrap(); 4665 assert!(db 4666 .load_key_entry( 4667 &KeyDescriptor { 4668 domain: Domain::APP, 4669 nspace: 0, 4670 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()), 4671 blob: None, 4672 }, 4673 KeyType::Client, 4674 KeyEntryLoadBits::BOTH, 4675 33, 4676 |_k, _av| Ok(()), 4677 ) 4678 .is_ok()); 4679 // We should only see a 2 here because we can only return 4680 // from load_key_entry when the `_key_guard` expires, 4681 // which happens at the end of the scope. 4682 assert_eq!(2, state2.load(Ordering::Relaxed)); 4683 }); 4684 4685 thread::sleep(std::time::Duration::from_millis(1000)); 4686 4687 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed)); 4688 4689 // Return the handle from this scope so we can join with the 4690 // secondary thread after the key id lock has expired. 4691 handle 4692 // This is where the `_key_guard` goes out of scope, 4693 // which is the reason for concurrent load_key_entry on the same key 4694 // to unblock. 4695 }; 4696 // Join with the secondary thread and unwrap, to propagate failing asserts to the 4697 // main test thread. We will not see failing asserts in secondary threads otherwise. 4698 handle.join().unwrap(); 4699 Ok(()) 4700 } 4701 4702 #[test] test_database_busy_error_code()4703 fn test_database_busy_error_code() { 4704 let temp_dir = 4705 TempDir::new("test_database_busy_error_code_").expect("Failed to create temp dir."); 4706 4707 let mut db1 = KeystoreDB::new(temp_dir.path(), None).expect("Failed to open database1."); 4708 let mut db2 = KeystoreDB::new(temp_dir.path(), None).expect("Failed to open database2."); 4709 4710 let _tx1 = db1 4711 .conn 4712 .transaction_with_behavior(TransactionBehavior::Immediate) 4713 .expect("Failed to create first transaction."); 4714 4715 let error = db2 4716 .conn 4717 .transaction_with_behavior(TransactionBehavior::Immediate) 4718 .context("Transaction begin failed.") 4719 .expect_err("This should fail."); 4720 let root_cause = error.root_cause(); 4721 if let Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseBusy, .. }) = 4722 root_cause.downcast_ref::<rusqlite::ffi::Error>() 4723 { 4724 return; 4725 } 4726 panic!( 4727 "Unexpected error {:?} \n{:?} \n{:?}", 4728 error, 4729 root_cause, 4730 root_cause.downcast_ref::<rusqlite::ffi::Error>() 4731 ) 4732 } 4733 4734 #[cfg(disabled)] 4735 #[test] test_large_number_of_concurrent_db_manipulations() -> Result<()>4736 fn test_large_number_of_concurrent_db_manipulations() -> Result<()> { 4737 let temp_dir = Arc::new( 4738 TempDir::new("test_large_number_of_concurrent_db_manipulations_") 4739 .expect("Failed to create temp dir."), 4740 ); 4741 4742 let test_begin = Instant::now(); 4743 4744 const KEY_COUNT: u32 = 500u32; 4745 let mut db = 4746 new_test_db_with_gc(temp_dir.path(), |_, _| Ok(())).expect("Failed to open database."); 4747 const OPEN_DB_COUNT: u32 = 50u32; 4748 4749 let mut actual_key_count = KEY_COUNT; 4750 // First insert KEY_COUNT keys. 4751 for count in 0..KEY_COUNT { 4752 if Instant::now().duration_since(test_begin) >= Duration::from_secs(15) { 4753 actual_key_count = count; 4754 break; 4755 } 4756 let alias = format!("test_alias_{}", count); 4757 make_test_key_entry(&mut db, Domain::APP, 1, &alias, None) 4758 .expect("Failed to make key entry."); 4759 } 4760 4761 // Insert more keys from a different thread and into a different namespace. 4762 let temp_dir1 = temp_dir.clone(); 4763 let handle1 = thread::spawn(move || { 4764 let mut db = new_test_db_with_gc(temp_dir1.path(), |_, _| Ok(())) 4765 .expect("Failed to open database."); 4766 4767 for count in 0..actual_key_count { 4768 if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) { 4769 return; 4770 } 4771 let alias = format!("test_alias_{}", count); 4772 make_test_key_entry(&mut db, Domain::APP, 2, &alias, None) 4773 .expect("Failed to make key entry."); 4774 } 4775 4776 // then unbind them again. 4777 for count in 0..actual_key_count { 4778 if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) { 4779 return; 4780 } 4781 let key = KeyDescriptor { 4782 domain: Domain::APP, 4783 nspace: -1, 4784 alias: Some(format!("test_alias_{}", count)), 4785 blob: None, 4786 }; 4787 db.unbind_key(&key, KeyType::Client, 2, |_, _| Ok(())).expect("Unbind Failed."); 4788 } 4789 }); 4790 4791 // And start unbinding the first set of keys. 4792 let temp_dir2 = temp_dir.clone(); 4793 let handle2 = thread::spawn(move || { 4794 let mut db = new_test_db_with_gc(temp_dir2.path(), |_, _| Ok(())) 4795 .expect("Failed to open database."); 4796 4797 for count in 0..actual_key_count { 4798 if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) { 4799 return; 4800 } 4801 let key = KeyDescriptor { 4802 domain: Domain::APP, 4803 nspace: -1, 4804 alias: Some(format!("test_alias_{}", count)), 4805 blob: None, 4806 }; 4807 db.unbind_key(&key, KeyType::Client, 1, |_, _| Ok(())).expect("Unbind Failed."); 4808 } 4809 }); 4810 4811 // While a lot of inserting and deleting is going on we have to open database connections 4812 // successfully and use them. 4813 // This clone is not redundant, because temp_dir needs to be kept alive until db goes 4814 // out of scope. 4815 #[allow(clippy::redundant_clone)] 4816 let temp_dir4 = temp_dir.clone(); 4817 let handle4 = thread::spawn(move || { 4818 for count in 0..OPEN_DB_COUNT { 4819 if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) { 4820 return; 4821 } 4822 let mut db = new_test_db_with_gc(temp_dir4.path(), |_, _| Ok(())) 4823 .expect("Failed to open database."); 4824 4825 let alias = format!("test_alias_{}", count); 4826 make_test_key_entry(&mut db, Domain::APP, 3, &alias, None) 4827 .expect("Failed to make key entry."); 4828 let key = KeyDescriptor { 4829 domain: Domain::APP, 4830 nspace: -1, 4831 alias: Some(alias), 4832 blob: None, 4833 }; 4834 db.unbind_key(&key, KeyType::Client, 3, |_, _| Ok(())).expect("Unbind Failed."); 4835 } 4836 }); 4837 4838 handle1.join().expect("Thread 1 panicked."); 4839 handle2.join().expect("Thread 2 panicked."); 4840 handle4.join().expect("Thread 4 panicked."); 4841 4842 Ok(()) 4843 } 4844 4845 #[test] list() -> Result<()>4846 fn list() -> Result<()> { 4847 let temp_dir = TempDir::new("list_test")?; 4848 let mut db = KeystoreDB::new(temp_dir.path(), None)?; 4849 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[ 4850 (Domain::APP, 1, "test1"), 4851 (Domain::APP, 1, "test2"), 4852 (Domain::APP, 1, "test3"), 4853 (Domain::APP, 1, "test4"), 4854 (Domain::APP, 1, "test5"), 4855 (Domain::APP, 1, "test6"), 4856 (Domain::APP, 1, "test7"), 4857 (Domain::APP, 2, "test1"), 4858 (Domain::APP, 2, "test2"), 4859 (Domain::APP, 2, "test3"), 4860 (Domain::APP, 2, "test4"), 4861 (Domain::APP, 2, "test5"), 4862 (Domain::APP, 2, "test6"), 4863 (Domain::APP, 2, "test8"), 4864 (Domain::SELINUX, 100, "test1"), 4865 (Domain::SELINUX, 100, "test2"), 4866 (Domain::SELINUX, 100, "test3"), 4867 (Domain::SELINUX, 100, "test4"), 4868 (Domain::SELINUX, 100, "test5"), 4869 (Domain::SELINUX, 100, "test6"), 4870 (Domain::SELINUX, 100, "test9"), 4871 ]; 4872 4873 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES 4874 .iter() 4875 .map(|(domain, ns, alias)| { 4876 let entry = make_test_key_entry(&mut db, *domain, *ns, *alias, None) 4877 .unwrap_or_else(|e| { 4878 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e) 4879 }); 4880 (entry.id(), *ns) 4881 }) 4882 .collect(); 4883 4884 for (domain, namespace) in 4885 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)] 4886 { 4887 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES 4888 .iter() 4889 .filter_map(|(domain, ns, alias)| match ns { 4890 ns if *ns == *namespace => Some(KeyDescriptor { 4891 domain: *domain, 4892 nspace: *ns, 4893 alias: Some(alias.to_string()), 4894 blob: None, 4895 }), 4896 _ => None, 4897 }) 4898 .collect(); 4899 list_o_descriptors.sort(); 4900 let mut list_result = db.list(*domain, *namespace, KeyType::Client)?; 4901 list_result.sort(); 4902 assert_eq!(list_o_descriptors, list_result); 4903 4904 let mut list_o_ids: Vec<i64> = list_o_descriptors 4905 .into_iter() 4906 .map(|d| { 4907 let (_, entry) = db 4908 .load_key_entry( 4909 &d, 4910 KeyType::Client, 4911 KeyEntryLoadBits::NONE, 4912 *namespace as u32, 4913 |_, _| Ok(()), 4914 ) 4915 .unwrap(); 4916 entry.id() 4917 }) 4918 .collect(); 4919 list_o_ids.sort_unstable(); 4920 let mut loaded_entries: Vec<i64> = list_o_keys 4921 .iter() 4922 .filter_map(|(id, ns)| match ns { 4923 ns if *ns == *namespace => Some(*id), 4924 _ => None, 4925 }) 4926 .collect(); 4927 loaded_entries.sort_unstable(); 4928 assert_eq!(list_o_ids, loaded_entries); 4929 } 4930 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101, KeyType::Client)?); 4931 4932 Ok(()) 4933 } 4934 4935 // Helpers 4936 4937 // Checks that the given result is an error containing the given string. check_result_is_error_containing_string<T>(result: Result<T>, target: &str)4938 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) { 4939 let error_str = format!( 4940 "{:#?}", 4941 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target)) 4942 ); 4943 assert!( 4944 error_str.contains(target), 4945 "The string \"{}\" should contain \"{}\"", 4946 error_str, 4947 target 4948 ); 4949 } 4950 4951 #[derive(Debug, PartialEq)] 4952 struct KeyEntryRow { 4953 id: i64, 4954 key_type: KeyType, 4955 domain: Option<Domain>, 4956 namespace: Option<i64>, 4957 alias: Option<String>, 4958 state: KeyLifeCycle, 4959 km_uuid: Option<Uuid>, 4960 } 4961 get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>>4962 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> { 4963 db.conn 4964 .prepare("SELECT * FROM persistent.keyentry;")? 4965 .query_map(NO_PARAMS, |row| { 4966 Ok(KeyEntryRow { 4967 id: row.get(0)?, 4968 key_type: row.get(1)?, 4969 domain: match row.get(2)? { 4970 Some(i) => Some(Domain(i)), 4971 None => None, 4972 }, 4973 namespace: row.get(3)?, 4974 alias: row.get(4)?, 4975 state: row.get(5)?, 4976 km_uuid: row.get(6)?, 4977 }) 4978 })? 4979 .map(|r| r.context("Could not read keyentry row.")) 4980 .collect::<Result<Vec<_>>>() 4981 } 4982 4983 struct RemoteProvValues { 4984 cert_chain: Vec<u8>, 4985 priv_key: Vec<u8>, 4986 batch_cert: Vec<u8>, 4987 } 4988 load_attestation_key_pool( db: &mut KeystoreDB, expiration_date: i64, namespace: i64, base_byte: u8, ) -> Result<RemoteProvValues>4989 fn load_attestation_key_pool( 4990 db: &mut KeystoreDB, 4991 expiration_date: i64, 4992 namespace: i64, 4993 base_byte: u8, 4994 ) -> Result<RemoteProvValues> { 4995 let public_key: Vec<u8> = vec![base_byte, 0x02 * base_byte]; 4996 let cert_chain: Vec<u8> = vec![0x03 * base_byte, 0x04 * base_byte]; 4997 let priv_key: Vec<u8> = vec![0x05 * base_byte, 0x06 * base_byte]; 4998 let raw_public_key: Vec<u8> = vec![0x0b * base_byte, 0x0c * base_byte]; 4999 let batch_cert: Vec<u8> = vec![base_byte * 0x0d, base_byte * 0x0e]; 5000 db.create_attestation_key_entry(&public_key, &raw_public_key, &priv_key, &KEYSTORE_UUID)?; 5001 db.store_signed_attestation_certificate_chain( 5002 &raw_public_key, 5003 &batch_cert, 5004 &cert_chain, 5005 expiration_date, 5006 &KEYSTORE_UUID, 5007 )?; 5008 db.assign_attestation_key(Domain::APP, namespace, &KEYSTORE_UUID)?; 5009 Ok(RemoteProvValues { cert_chain, priv_key, batch_cert }) 5010 } 5011 5012 // Note: The parameters and SecurityLevel associations are nonsensical. This 5013 // collection is only used to check if the parameters are preserved as expected by the 5014 // database. make_test_params(max_usage_count: Option<i32>) -> Vec<KeyParameter>5015 fn make_test_params(max_usage_count: Option<i32>) -> Vec<KeyParameter> { 5016 let mut params = vec![ 5017 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT), 5018 KeyParameter::new( 5019 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN), 5020 SecurityLevel::TRUSTED_ENVIRONMENT, 5021 ), 5022 KeyParameter::new( 5023 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT), 5024 SecurityLevel::TRUSTED_ENVIRONMENT, 5025 ), 5026 KeyParameter::new( 5027 KeyParameterValue::Algorithm(Algorithm::RSA), 5028 SecurityLevel::TRUSTED_ENVIRONMENT, 5029 ), 5030 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT), 5031 KeyParameter::new( 5032 KeyParameterValue::BlockMode(BlockMode::ECB), 5033 SecurityLevel::TRUSTED_ENVIRONMENT, 5034 ), 5035 KeyParameter::new( 5036 KeyParameterValue::BlockMode(BlockMode::GCM), 5037 SecurityLevel::TRUSTED_ENVIRONMENT, 5038 ), 5039 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX), 5040 KeyParameter::new( 5041 KeyParameterValue::Digest(Digest::MD5), 5042 SecurityLevel::TRUSTED_ENVIRONMENT, 5043 ), 5044 KeyParameter::new( 5045 KeyParameterValue::Digest(Digest::SHA_2_224), 5046 SecurityLevel::TRUSTED_ENVIRONMENT, 5047 ), 5048 KeyParameter::new( 5049 KeyParameterValue::Digest(Digest::SHA_2_256), 5050 SecurityLevel::STRONGBOX, 5051 ), 5052 KeyParameter::new( 5053 KeyParameterValue::PaddingMode(PaddingMode::NONE), 5054 SecurityLevel::TRUSTED_ENVIRONMENT, 5055 ), 5056 KeyParameter::new( 5057 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP), 5058 SecurityLevel::TRUSTED_ENVIRONMENT, 5059 ), 5060 KeyParameter::new( 5061 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS), 5062 SecurityLevel::STRONGBOX, 5063 ), 5064 KeyParameter::new( 5065 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN), 5066 SecurityLevel::TRUSTED_ENVIRONMENT, 5067 ), 5068 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT), 5069 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX), 5070 KeyParameter::new( 5071 KeyParameterValue::EcCurve(EcCurve::P_224), 5072 SecurityLevel::TRUSTED_ENVIRONMENT, 5073 ), 5074 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX), 5075 KeyParameter::new( 5076 KeyParameterValue::EcCurve(EcCurve::P_384), 5077 SecurityLevel::TRUSTED_ENVIRONMENT, 5078 ), 5079 KeyParameter::new( 5080 KeyParameterValue::EcCurve(EcCurve::P_521), 5081 SecurityLevel::TRUSTED_ENVIRONMENT, 5082 ), 5083 KeyParameter::new( 5084 KeyParameterValue::RSAPublicExponent(3), 5085 SecurityLevel::TRUSTED_ENVIRONMENT, 5086 ), 5087 KeyParameter::new( 5088 KeyParameterValue::IncludeUniqueID, 5089 SecurityLevel::TRUSTED_ENVIRONMENT, 5090 ), 5091 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX), 5092 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX), 5093 KeyParameter::new( 5094 KeyParameterValue::ActiveDateTime(1234567890), 5095 SecurityLevel::STRONGBOX, 5096 ), 5097 KeyParameter::new( 5098 KeyParameterValue::OriginationExpireDateTime(1234567890), 5099 SecurityLevel::TRUSTED_ENVIRONMENT, 5100 ), 5101 KeyParameter::new( 5102 KeyParameterValue::UsageExpireDateTime(1234567890), 5103 SecurityLevel::TRUSTED_ENVIRONMENT, 5104 ), 5105 KeyParameter::new( 5106 KeyParameterValue::MinSecondsBetweenOps(1234567890), 5107 SecurityLevel::TRUSTED_ENVIRONMENT, 5108 ), 5109 KeyParameter::new( 5110 KeyParameterValue::MaxUsesPerBoot(1234567890), 5111 SecurityLevel::TRUSTED_ENVIRONMENT, 5112 ), 5113 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX), 5114 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX), 5115 KeyParameter::new( 5116 KeyParameterValue::NoAuthRequired, 5117 SecurityLevel::TRUSTED_ENVIRONMENT, 5118 ), 5119 KeyParameter::new( 5120 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD), 5121 SecurityLevel::TRUSTED_ENVIRONMENT, 5122 ), 5123 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE), 5124 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE), 5125 KeyParameter::new( 5126 KeyParameterValue::TrustedUserPresenceRequired, 5127 SecurityLevel::TRUSTED_ENVIRONMENT, 5128 ), 5129 KeyParameter::new( 5130 KeyParameterValue::TrustedConfirmationRequired, 5131 SecurityLevel::TRUSTED_ENVIRONMENT, 5132 ), 5133 KeyParameter::new( 5134 KeyParameterValue::UnlockedDeviceRequired, 5135 SecurityLevel::TRUSTED_ENVIRONMENT, 5136 ), 5137 KeyParameter::new( 5138 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]), 5139 SecurityLevel::SOFTWARE, 5140 ), 5141 KeyParameter::new( 5142 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]), 5143 SecurityLevel::SOFTWARE, 5144 ), 5145 KeyParameter::new( 5146 KeyParameterValue::CreationDateTime(12345677890), 5147 SecurityLevel::SOFTWARE, 5148 ), 5149 KeyParameter::new( 5150 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED), 5151 SecurityLevel::TRUSTED_ENVIRONMENT, 5152 ), 5153 KeyParameter::new( 5154 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]), 5155 SecurityLevel::TRUSTED_ENVIRONMENT, 5156 ), 5157 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT), 5158 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE), 5159 KeyParameter::new( 5160 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]), 5161 SecurityLevel::SOFTWARE, 5162 ), 5163 KeyParameter::new( 5164 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]), 5165 SecurityLevel::TRUSTED_ENVIRONMENT, 5166 ), 5167 KeyParameter::new( 5168 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]), 5169 SecurityLevel::TRUSTED_ENVIRONMENT, 5170 ), 5171 KeyParameter::new( 5172 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]), 5173 SecurityLevel::TRUSTED_ENVIRONMENT, 5174 ), 5175 KeyParameter::new( 5176 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]), 5177 SecurityLevel::TRUSTED_ENVIRONMENT, 5178 ), 5179 KeyParameter::new( 5180 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]), 5181 SecurityLevel::TRUSTED_ENVIRONMENT, 5182 ), 5183 KeyParameter::new( 5184 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]), 5185 SecurityLevel::TRUSTED_ENVIRONMENT, 5186 ), 5187 KeyParameter::new( 5188 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]), 5189 SecurityLevel::TRUSTED_ENVIRONMENT, 5190 ), 5191 KeyParameter::new( 5192 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]), 5193 SecurityLevel::TRUSTED_ENVIRONMENT, 5194 ), 5195 KeyParameter::new( 5196 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]), 5197 SecurityLevel::TRUSTED_ENVIRONMENT, 5198 ), 5199 KeyParameter::new( 5200 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]), 5201 SecurityLevel::TRUSTED_ENVIRONMENT, 5202 ), 5203 KeyParameter::new( 5204 KeyParameterValue::VendorPatchLevel(3), 5205 SecurityLevel::TRUSTED_ENVIRONMENT, 5206 ), 5207 KeyParameter::new( 5208 KeyParameterValue::BootPatchLevel(4), 5209 SecurityLevel::TRUSTED_ENVIRONMENT, 5210 ), 5211 KeyParameter::new( 5212 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]), 5213 SecurityLevel::TRUSTED_ENVIRONMENT, 5214 ), 5215 KeyParameter::new( 5216 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]), 5217 SecurityLevel::TRUSTED_ENVIRONMENT, 5218 ), 5219 KeyParameter::new( 5220 KeyParameterValue::MacLength(256), 5221 SecurityLevel::TRUSTED_ENVIRONMENT, 5222 ), 5223 KeyParameter::new( 5224 KeyParameterValue::ResetSinceIdRotation, 5225 SecurityLevel::TRUSTED_ENVIRONMENT, 5226 ), 5227 KeyParameter::new( 5228 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]), 5229 SecurityLevel::TRUSTED_ENVIRONMENT, 5230 ), 5231 ]; 5232 if let Some(value) = max_usage_count { 5233 params.push(KeyParameter::new( 5234 KeyParameterValue::UsageCountLimit(value), 5235 SecurityLevel::SOFTWARE, 5236 )); 5237 } 5238 params 5239 } 5240 make_test_key_entry( db: &mut KeystoreDB, domain: Domain, namespace: i64, alias: &str, max_usage_count: Option<i32>, ) -> Result<KeyIdGuard>5241 fn make_test_key_entry( 5242 db: &mut KeystoreDB, 5243 domain: Domain, 5244 namespace: i64, 5245 alias: &str, 5246 max_usage_count: Option<i32>, 5247 ) -> Result<KeyIdGuard> { 5248 let key_id = db.create_key_entry(&domain, &namespace, KeyType::Client, &KEYSTORE_UUID)?; 5249 let mut blob_metadata = BlobMetaData::new(); 5250 blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password)); 5251 blob_metadata.add(BlobMetaEntry::Salt(vec![1, 2, 3])); 5252 blob_metadata.add(BlobMetaEntry::Iv(vec![2, 3, 1])); 5253 blob_metadata.add(BlobMetaEntry::AeadTag(vec![3, 1, 2])); 5254 blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID)); 5255 5256 db.set_blob( 5257 &key_id, 5258 SubComponentType::KEY_BLOB, 5259 Some(TEST_KEY_BLOB), 5260 Some(&blob_metadata), 5261 )?; 5262 db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB), None)?; 5263 db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB), None)?; 5264 5265 let params = make_test_params(max_usage_count); 5266 db.insert_keyparameter(&key_id, ¶ms)?; 5267 5268 let mut metadata = KeyMetaData::new(); 5269 metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789))); 5270 db.insert_key_metadata(&key_id, &metadata)?; 5271 rebind_alias(db, &key_id, alias, domain, namespace)?; 5272 Ok(key_id) 5273 } 5274 make_test_key_entry_test_vector(key_id: i64, max_usage_count: Option<i32>) -> KeyEntry5275 fn make_test_key_entry_test_vector(key_id: i64, max_usage_count: Option<i32>) -> KeyEntry { 5276 let params = make_test_params(max_usage_count); 5277 5278 let mut blob_metadata = BlobMetaData::new(); 5279 blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password)); 5280 blob_metadata.add(BlobMetaEntry::Salt(vec![1, 2, 3])); 5281 blob_metadata.add(BlobMetaEntry::Iv(vec![2, 3, 1])); 5282 blob_metadata.add(BlobMetaEntry::AeadTag(vec![3, 1, 2])); 5283 blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID)); 5284 5285 let mut metadata = KeyMetaData::new(); 5286 metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789))); 5287 5288 KeyEntry { 5289 id: key_id, 5290 key_blob_info: Some((TEST_KEY_BLOB.to_vec(), blob_metadata)), 5291 cert: Some(TEST_CERT_BLOB.to_vec()), 5292 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()), 5293 km_uuid: KEYSTORE_UUID, 5294 parameters: params, 5295 metadata, 5296 pure_cert: false, 5297 } 5298 } 5299 make_bootlevel_key_entry( db: &mut KeystoreDB, domain: Domain, namespace: i64, alias: &str, logical_only: bool, ) -> Result<KeyIdGuard>5300 fn make_bootlevel_key_entry( 5301 db: &mut KeystoreDB, 5302 domain: Domain, 5303 namespace: i64, 5304 alias: &str, 5305 logical_only: bool, 5306 ) -> Result<KeyIdGuard> { 5307 let key_id = db.create_key_entry(&domain, &namespace, KeyType::Client, &KEYSTORE_UUID)?; 5308 let mut blob_metadata = BlobMetaData::new(); 5309 if !logical_only { 5310 blob_metadata.add(BlobMetaEntry::MaxBootLevel(3)); 5311 } 5312 blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID)); 5313 5314 db.set_blob( 5315 &key_id, 5316 SubComponentType::KEY_BLOB, 5317 Some(TEST_KEY_BLOB), 5318 Some(&blob_metadata), 5319 )?; 5320 db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB), None)?; 5321 db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB), None)?; 5322 5323 let mut params = make_test_params(None); 5324 params.push(KeyParameter::new(KeyParameterValue::MaxBootLevel(3), SecurityLevel::KEYSTORE)); 5325 5326 db.insert_keyparameter(&key_id, ¶ms)?; 5327 5328 let mut metadata = KeyMetaData::new(); 5329 metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789))); 5330 db.insert_key_metadata(&key_id, &metadata)?; 5331 rebind_alias(db, &key_id, alias, domain, namespace)?; 5332 Ok(key_id) 5333 } 5334 make_bootlevel_test_key_entry_test_vector(key_id: i64, logical_only: bool) -> KeyEntry5335 fn make_bootlevel_test_key_entry_test_vector(key_id: i64, logical_only: bool) -> KeyEntry { 5336 let mut params = make_test_params(None); 5337 params.push(KeyParameter::new(KeyParameterValue::MaxBootLevel(3), SecurityLevel::KEYSTORE)); 5338 5339 let mut blob_metadata = BlobMetaData::new(); 5340 if !logical_only { 5341 blob_metadata.add(BlobMetaEntry::MaxBootLevel(3)); 5342 } 5343 blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID)); 5344 5345 let mut metadata = KeyMetaData::new(); 5346 metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789))); 5347 5348 KeyEntry { 5349 id: key_id, 5350 key_blob_info: Some((TEST_KEY_BLOB.to_vec(), blob_metadata)), 5351 cert: Some(TEST_CERT_BLOB.to_vec()), 5352 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()), 5353 km_uuid: KEYSTORE_UUID, 5354 parameters: params, 5355 metadata, 5356 pure_cert: false, 5357 } 5358 } 5359 debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()>5360 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> { 5361 let mut stmt = db.conn.prepare( 5362 "SELECT id, key_type, domain, namespace, alias, state, km_uuid FROM persistent.keyentry;", 5363 )?; 5364 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle, Uuid), _, _>( 5365 NO_PARAMS, 5366 |row| { 5367 Ok(( 5368 row.get(0)?, 5369 row.get(1)?, 5370 row.get(2)?, 5371 row.get(3)?, 5372 row.get(4)?, 5373 row.get(5)?, 5374 row.get(6)?, 5375 )) 5376 }, 5377 )?; 5378 5379 println!("Key entry table rows:"); 5380 for r in rows { 5381 let (id, key_type, domain, namespace, alias, state, km_uuid) = r.unwrap(); 5382 println!( 5383 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?} KmUuid: {:?}", 5384 id, key_type, domain, namespace, alias, state, km_uuid 5385 ); 5386 } 5387 Ok(()) 5388 } 5389 debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()>5390 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> { 5391 let mut stmt = db 5392 .conn 5393 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?; 5394 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| { 5395 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?)) 5396 })?; 5397 5398 println!("Grant table rows:"); 5399 for r in rows { 5400 let (id, gt, ki, av) = r.unwrap(); 5401 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av); 5402 } 5403 Ok(()) 5404 } 5405 5406 // Use a custom random number generator that repeats each number once. 5407 // This allows us to test repeated elements. 5408 5409 thread_local! { 5410 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0); 5411 } 5412 reset_random()5413 fn reset_random() { 5414 RANDOM_COUNTER.with(|counter| { 5415 *counter.borrow_mut() = 0; 5416 }) 5417 } 5418 random() -> i645419 pub fn random() -> i64 { 5420 RANDOM_COUNTER.with(|counter| { 5421 let result = *counter.borrow() / 2; 5422 *counter.borrow_mut() += 1; 5423 result 5424 }) 5425 } 5426 5427 #[test] test_last_off_body() -> Result<()>5428 fn test_last_off_body() -> Result<()> { 5429 let mut db = new_test_db()?; 5430 db.insert_last_off_body(MonotonicRawTime::now()); 5431 let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?; 5432 tx.commit()?; 5433 let last_off_body_1 = db.get_last_off_body(); 5434 let one_second = Duration::from_secs(1); 5435 thread::sleep(one_second); 5436 db.update_last_off_body(MonotonicRawTime::now()); 5437 let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?; 5438 tx2.commit()?; 5439 let last_off_body_2 = db.get_last_off_body(); 5440 assert!(last_off_body_1 < last_off_body_2); 5441 Ok(()) 5442 } 5443 5444 #[test] test_unbind_keys_for_user() -> Result<()>5445 fn test_unbind_keys_for_user() -> Result<()> { 5446 let mut db = new_test_db()?; 5447 db.unbind_keys_for_user(1, false)?; 5448 5449 make_test_key_entry(&mut db, Domain::APP, 210000, TEST_ALIAS, None)?; 5450 make_test_key_entry(&mut db, Domain::APP, 110000, TEST_ALIAS, None)?; 5451 db.unbind_keys_for_user(2, false)?; 5452 5453 assert_eq!(1, db.list(Domain::APP, 110000, KeyType::Client)?.len()); 5454 assert_eq!(0, db.list(Domain::APP, 210000, KeyType::Client)?.len()); 5455 5456 db.unbind_keys_for_user(1, true)?; 5457 assert_eq!(0, db.list(Domain::APP, 110000, KeyType::Client)?.len()); 5458 5459 Ok(()) 5460 } 5461 5462 #[test] test_store_super_key() -> Result<()>5463 fn test_store_super_key() -> Result<()> { 5464 let mut db = new_test_db()?; 5465 let pw: keystore2_crypto::Password = (&b"xyzabc"[..]).into(); 5466 let super_key = keystore2_crypto::generate_aes256_key()?; 5467 let secret_bytes = b"keystore2 is great."; 5468 let (encrypted_secret, iv, tag) = 5469 keystore2_crypto::aes_gcm_encrypt(secret_bytes, &super_key)?; 5470 5471 let (encrypted_super_key, metadata) = 5472 SuperKeyManager::encrypt_with_password(&super_key, &pw)?; 5473 db.store_super_key( 5474 1, 5475 &USER_SUPER_KEY, 5476 &encrypted_super_key, 5477 &metadata, 5478 &KeyMetaData::new(), 5479 )?; 5480 5481 //check if super key exists 5482 assert!(db.key_exists(Domain::APP, 1, &USER_SUPER_KEY.alias, KeyType::Super)?); 5483 5484 let (_, key_entry) = db.load_super_key(&USER_SUPER_KEY, 1)?.unwrap(); 5485 let loaded_super_key = SuperKeyManager::extract_super_key_from_key_entry( 5486 USER_SUPER_KEY.algorithm, 5487 key_entry, 5488 &pw, 5489 None, 5490 )?; 5491 5492 let decrypted_secret_bytes = 5493 loaded_super_key.aes_gcm_decrypt(&encrypted_secret, &iv, &tag)?; 5494 assert_eq!(secret_bytes, &*decrypted_secret_bytes); 5495 Ok(()) 5496 } 5497 get_valid_statsd_storage_types() -> Vec<MetricsStorage>5498 fn get_valid_statsd_storage_types() -> Vec<MetricsStorage> { 5499 vec![ 5500 MetricsStorage::KEY_ENTRY, 5501 MetricsStorage::KEY_ENTRY_ID_INDEX, 5502 MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX, 5503 MetricsStorage::BLOB_ENTRY, 5504 MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX, 5505 MetricsStorage::KEY_PARAMETER, 5506 MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX, 5507 MetricsStorage::KEY_METADATA, 5508 MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX, 5509 MetricsStorage::GRANT, 5510 MetricsStorage::AUTH_TOKEN, 5511 MetricsStorage::BLOB_METADATA, 5512 MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX, 5513 ] 5514 } 5515 5516 /// Perform a simple check to ensure that we can query all the storage types 5517 /// that are supported by the DB. Check for reasonable values. 5518 #[test] test_query_all_valid_table_sizes() -> Result<()>5519 fn test_query_all_valid_table_sizes() -> Result<()> { 5520 const PAGE_SIZE: i32 = 4096; 5521 5522 let mut db = new_test_db()?; 5523 5524 for t in get_valid_statsd_storage_types() { 5525 let stat = db.get_storage_stat(t)?; 5526 // AuthToken can be less than a page since it's in a btree, not sqlite 5527 // TODO(b/187474736) stop using if-let here 5528 if let MetricsStorage::AUTH_TOKEN = t { 5529 } else { 5530 assert!(stat.size >= PAGE_SIZE); 5531 } 5532 assert!(stat.size >= stat.unused_size); 5533 } 5534 5535 Ok(()) 5536 } 5537 get_storage_stats_map(db: &mut KeystoreDB) -> BTreeMap<i32, StorageStats>5538 fn get_storage_stats_map(db: &mut KeystoreDB) -> BTreeMap<i32, StorageStats> { 5539 get_valid_statsd_storage_types() 5540 .into_iter() 5541 .map(|t| (t.0, db.get_storage_stat(t).unwrap())) 5542 .collect() 5543 } 5544 assert_storage_increased( db: &mut KeystoreDB, increased_storage_types: Vec<MetricsStorage>, baseline: &mut BTreeMap<i32, StorageStats>, )5545 fn assert_storage_increased( 5546 db: &mut KeystoreDB, 5547 increased_storage_types: Vec<MetricsStorage>, 5548 baseline: &mut BTreeMap<i32, StorageStats>, 5549 ) { 5550 for storage in increased_storage_types { 5551 // Verify the expected storage increased. 5552 let new = db.get_storage_stat(storage).unwrap(); 5553 let storage = storage; 5554 let old = &baseline[&storage.0]; 5555 assert!(new.size >= old.size, "{}: {} >= {}", storage.0, new.size, old.size); 5556 assert!( 5557 new.unused_size <= old.unused_size, 5558 "{}: {} <= {}", 5559 storage.0, 5560 new.unused_size, 5561 old.unused_size 5562 ); 5563 5564 // Update the baseline with the new value so that it succeeds in the 5565 // later comparison. 5566 baseline.insert(storage.0, new); 5567 } 5568 5569 // Get an updated map of the storage and verify there were no unexpected changes. 5570 let updated_stats = get_storage_stats_map(db); 5571 assert_eq!(updated_stats.len(), baseline.len()); 5572 5573 for &k in baseline.keys() { 5574 let stringify = |map: &BTreeMap<i32, StorageStats>| -> String { 5575 let mut s = String::new(); 5576 for &k in map.keys() { 5577 writeln!(&mut s, " {}: {}, {}", &k, map[&k].size, map[&k].unused_size) 5578 .expect("string concat failed"); 5579 } 5580 s 5581 }; 5582 5583 assert!( 5584 updated_stats[&k].size == baseline[&k].size 5585 && updated_stats[&k].unused_size == baseline[&k].unused_size, 5586 "updated_stats:\n{}\nbaseline:\n{}", 5587 stringify(&updated_stats), 5588 stringify(&baseline) 5589 ); 5590 } 5591 } 5592 5593 #[test] test_verify_key_table_size_reporting() -> Result<()>5594 fn test_verify_key_table_size_reporting() -> Result<()> { 5595 let mut db = new_test_db()?; 5596 let mut working_stats = get_storage_stats_map(&mut db); 5597 5598 let key_id = db.create_key_entry(&Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?; 5599 assert_storage_increased( 5600 &mut db, 5601 vec![ 5602 MetricsStorage::KEY_ENTRY, 5603 MetricsStorage::KEY_ENTRY_ID_INDEX, 5604 MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX, 5605 ], 5606 &mut working_stats, 5607 ); 5608 5609 let mut blob_metadata = BlobMetaData::new(); 5610 blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password)); 5611 db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB), None)?; 5612 assert_storage_increased( 5613 &mut db, 5614 vec![ 5615 MetricsStorage::BLOB_ENTRY, 5616 MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX, 5617 MetricsStorage::BLOB_METADATA, 5618 MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX, 5619 ], 5620 &mut working_stats, 5621 ); 5622 5623 let params = make_test_params(None); 5624 db.insert_keyparameter(&key_id, ¶ms)?; 5625 assert_storage_increased( 5626 &mut db, 5627 vec![MetricsStorage::KEY_PARAMETER, MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX], 5628 &mut working_stats, 5629 ); 5630 5631 let mut metadata = KeyMetaData::new(); 5632 metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789))); 5633 db.insert_key_metadata(&key_id, &metadata)?; 5634 assert_storage_increased( 5635 &mut db, 5636 vec![MetricsStorage::KEY_METADATA, MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX], 5637 &mut working_stats, 5638 ); 5639 5640 let mut sum = 0; 5641 for stat in working_stats.values() { 5642 sum += stat.size; 5643 } 5644 let total = db.get_storage_stat(MetricsStorage::DATABASE)?.size; 5645 assert!(sum <= total, "Expected sum <= total. sum: {}, total: {}", sum, total); 5646 5647 Ok(()) 5648 } 5649 5650 #[test] test_verify_auth_table_size_reporting() -> Result<()>5651 fn test_verify_auth_table_size_reporting() -> Result<()> { 5652 let mut db = new_test_db()?; 5653 let mut working_stats = get_storage_stats_map(&mut db); 5654 db.insert_auth_token(&HardwareAuthToken { 5655 challenge: 123, 5656 userId: 456, 5657 authenticatorId: 789, 5658 authenticatorType: kmhw_authenticator_type::ANY, 5659 timestamp: Timestamp { milliSeconds: 10 }, 5660 mac: b"mac".to_vec(), 5661 }); 5662 assert_storage_increased(&mut db, vec![MetricsStorage::AUTH_TOKEN], &mut working_stats); 5663 Ok(()) 5664 } 5665 5666 #[test] test_verify_grant_table_size_reporting() -> Result<()>5667 fn test_verify_grant_table_size_reporting() -> Result<()> { 5668 const OWNER: i64 = 1; 5669 let mut db = new_test_db()?; 5670 make_test_key_entry(&mut db, Domain::APP, OWNER, TEST_ALIAS, None)?; 5671 5672 let mut working_stats = get_storage_stats_map(&mut db); 5673 db.grant( 5674 &KeyDescriptor { 5675 domain: Domain::APP, 5676 nspace: 0, 5677 alias: Some(TEST_ALIAS.to_string()), 5678 blob: None, 5679 }, 5680 OWNER as u32, 5681 123, 5682 key_perm_set![KeyPerm::use_()], 5683 |_, _| Ok(()), 5684 )?; 5685 5686 assert_storage_increased(&mut db, vec![MetricsStorage::GRANT], &mut working_stats); 5687 5688 Ok(()) 5689 } 5690 5691 #[test] find_auth_token_entry_returns_latest() -> Result<()>5692 fn find_auth_token_entry_returns_latest() -> Result<()> { 5693 let mut db = new_test_db()?; 5694 db.insert_auth_token(&HardwareAuthToken { 5695 challenge: 123, 5696 userId: 456, 5697 authenticatorId: 789, 5698 authenticatorType: kmhw_authenticator_type::ANY, 5699 timestamp: Timestamp { milliSeconds: 10 }, 5700 mac: b"mac0".to_vec(), 5701 }); 5702 std::thread::sleep(std::time::Duration::from_millis(1)); 5703 db.insert_auth_token(&HardwareAuthToken { 5704 challenge: 123, 5705 userId: 457, 5706 authenticatorId: 789, 5707 authenticatorType: kmhw_authenticator_type::ANY, 5708 timestamp: Timestamp { milliSeconds: 12 }, 5709 mac: b"mac1".to_vec(), 5710 }); 5711 std::thread::sleep(std::time::Duration::from_millis(1)); 5712 db.insert_auth_token(&HardwareAuthToken { 5713 challenge: 123, 5714 userId: 458, 5715 authenticatorId: 789, 5716 authenticatorType: kmhw_authenticator_type::ANY, 5717 timestamp: Timestamp { milliSeconds: 3 }, 5718 mac: b"mac2".to_vec(), 5719 }); 5720 // All three entries are in the database 5721 assert_eq!(db.perboot.auth_tokens_len(), 3); 5722 // It selected the most recent timestamp 5723 assert_eq!(db.find_auth_token_entry(|_| true).unwrap().0.auth_token.mac, b"mac2".to_vec()); 5724 Ok(()) 5725 } 5726 5727 #[test] test_load_key_descriptor() -> Result<()>5728 fn test_load_key_descriptor() -> Result<()> { 5729 let mut db = new_test_db()?; 5730 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None)?.0; 5731 5732 let key = db.load_key_descriptor(key_id)?.unwrap(); 5733 5734 assert_eq!(key.domain, Domain::APP); 5735 assert_eq!(key.nspace, 1); 5736 assert_eq!(key.alias, Some(TEST_ALIAS.to_string())); 5737 5738 // No such id 5739 assert_eq!(db.load_key_descriptor(key_id + 1)?, None); 5740 Ok(()) 5741 } 5742 } 5743