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