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