1*e1997b9aSAndroid Build Coastguard Worker // Copyright 2020, The Android Open Source Project 2*e1997b9aSAndroid Build Coastguard Worker // 3*e1997b9aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*e1997b9aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*e1997b9aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*e1997b9aSAndroid Build Coastguard Worker // 7*e1997b9aSAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 8*e1997b9aSAndroid Build Coastguard Worker // 9*e1997b9aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*e1997b9aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*e1997b9aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e1997b9aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*e1997b9aSAndroid Build Coastguard Worker // limitations under the License. 14*e1997b9aSAndroid Build Coastguard Worker 15*e1997b9aSAndroid Build Coastguard Worker //! This is the Keystore 2.0 database module. 16*e1997b9aSAndroid Build Coastguard Worker //! The database module provides a connection to the backing SQLite store. 17*e1997b9aSAndroid Build Coastguard Worker //! We have two databases one for persistent key blob storage and one for 18*e1997b9aSAndroid Build Coastguard Worker //! items that have a per boot life cycle. 19*e1997b9aSAndroid Build Coastguard Worker //! 20*e1997b9aSAndroid Build Coastguard Worker //! ## Persistent database 21*e1997b9aSAndroid Build Coastguard Worker //! The persistent database has tables for key blobs. They are organized 22*e1997b9aSAndroid Build Coastguard Worker //! as follows: 23*e1997b9aSAndroid Build Coastguard Worker //! The `keyentry` table is the primary table for key entries. It is 24*e1997b9aSAndroid Build Coastguard Worker //! accompanied by two tables for blobs and parameters. 25*e1997b9aSAndroid Build Coastguard Worker //! Each key entry occupies exactly one row in the `keyentry` table and 26*e1997b9aSAndroid Build Coastguard Worker //! zero or more rows in the tables `blobentry` and `keyparameter`. 27*e1997b9aSAndroid Build Coastguard Worker //! 28*e1997b9aSAndroid Build Coastguard Worker //! ## Per boot database 29*e1997b9aSAndroid Build Coastguard Worker //! The per boot database stores items with a per boot lifecycle. 30*e1997b9aSAndroid Build Coastguard Worker //! Currently, there is only the `grant` table in this database. 31*e1997b9aSAndroid Build Coastguard Worker //! Grants are references to a key that can be used to access a key by 32*e1997b9aSAndroid Build Coastguard Worker //! clients that don't own that key. Grants can only be created by the 33*e1997b9aSAndroid Build Coastguard Worker //! owner of a key. And only certain components can create grants. 34*e1997b9aSAndroid Build Coastguard Worker //! This is governed by SEPolicy. 35*e1997b9aSAndroid Build Coastguard Worker //! 36*e1997b9aSAndroid Build Coastguard Worker //! ## Access control 37*e1997b9aSAndroid Build Coastguard Worker //! Some database functions that load keys or create grants perform 38*e1997b9aSAndroid Build Coastguard Worker //! access control. This is because in some cases access control 39*e1997b9aSAndroid Build Coastguard Worker //! can only be performed after some information about the designated 40*e1997b9aSAndroid Build Coastguard Worker //! key was loaded from the database. To decouple the permission checks 41*e1997b9aSAndroid Build Coastguard Worker //! from the database module these functions take permission check 42*e1997b9aSAndroid Build Coastguard Worker //! callbacks. 43*e1997b9aSAndroid Build Coastguard Worker 44*e1997b9aSAndroid Build Coastguard Worker mod perboot; 45*e1997b9aSAndroid Build Coastguard Worker pub(crate) mod utils; 46*e1997b9aSAndroid Build Coastguard Worker mod versioning; 47*e1997b9aSAndroid Build Coastguard Worker 48*e1997b9aSAndroid Build Coastguard Worker #[cfg(test)] 49*e1997b9aSAndroid Build Coastguard Worker pub mod tests; 50*e1997b9aSAndroid Build Coastguard Worker 51*e1997b9aSAndroid Build Coastguard Worker use crate::gc::Gc; 52*e1997b9aSAndroid Build Coastguard Worker use crate::impl_metadata; // This is in database/utils.rs 53*e1997b9aSAndroid Build Coastguard Worker use crate::key_parameter::{KeyParameter, KeyParameterValue, Tag}; 54*e1997b9aSAndroid Build Coastguard Worker use crate::ks_err; 55*e1997b9aSAndroid Build Coastguard Worker use crate::permission::KeyPermSet; 56*e1997b9aSAndroid Build Coastguard Worker use crate::utils::{get_current_time_in_milliseconds, watchdog as wd, AID_USER_OFFSET}; 57*e1997b9aSAndroid Build Coastguard Worker use crate::{ 58*e1997b9aSAndroid Build Coastguard Worker error::{Error as KsError, ErrorCode, ResponseCode}, 59*e1997b9aSAndroid Build Coastguard Worker super_key::SuperKeyType, 60*e1997b9aSAndroid Build Coastguard Worker }; 61*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ 62*e1997b9aSAndroid Build Coastguard Worker HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType, 63*e1997b9aSAndroid Build Coastguard Worker SecurityLevel::SecurityLevel, 64*e1997b9aSAndroid Build Coastguard Worker }; 65*e1997b9aSAndroid Build Coastguard Worker use android_security_metrics::aidl::android::security::metrics::{ 66*e1997b9aSAndroid Build Coastguard Worker Storage::Storage as MetricsStorage, StorageStats::StorageStats, 67*e1997b9aSAndroid Build Coastguard Worker }; 68*e1997b9aSAndroid Build Coastguard Worker use android_system_keystore2::aidl::android::system::keystore2::{ 69*e1997b9aSAndroid Build Coastguard Worker Domain::Domain, KeyDescriptor::KeyDescriptor, 70*e1997b9aSAndroid Build Coastguard Worker }; 71*e1997b9aSAndroid Build Coastguard Worker use anyhow::{anyhow, Context, Result}; 72*e1997b9aSAndroid Build Coastguard Worker use keystore2_flags; 73*e1997b9aSAndroid Build Coastguard Worker use std::{convert::TryFrom, convert::TryInto, ops::Deref, sync::LazyLock, time::SystemTimeError}; 74*e1997b9aSAndroid Build Coastguard Worker use utils as db_utils; 75*e1997b9aSAndroid Build Coastguard Worker use utils::SqlField; 76*e1997b9aSAndroid Build Coastguard Worker 77*e1997b9aSAndroid Build Coastguard Worker use keystore2_crypto::ZVec; 78*e1997b9aSAndroid Build Coastguard Worker use log::error; 79*e1997b9aSAndroid Build Coastguard Worker #[cfg(not(test))] 80*e1997b9aSAndroid Build Coastguard Worker use rand::prelude::random; 81*e1997b9aSAndroid Build Coastguard Worker use rusqlite::{ 82*e1997b9aSAndroid Build Coastguard Worker params, params_from_iter, 83*e1997b9aSAndroid Build Coastguard Worker types::FromSql, 84*e1997b9aSAndroid Build Coastguard Worker types::FromSqlResult, 85*e1997b9aSAndroid Build Coastguard Worker types::ToSqlOutput, 86*e1997b9aSAndroid Build Coastguard Worker types::{FromSqlError, Value, ValueRef}, 87*e1997b9aSAndroid Build Coastguard Worker Connection, OptionalExtension, ToSql, Transaction, 88*e1997b9aSAndroid Build Coastguard Worker }; 89*e1997b9aSAndroid Build Coastguard Worker 90*e1997b9aSAndroid Build Coastguard Worker use std::{ 91*e1997b9aSAndroid Build Coastguard Worker collections::{HashMap, HashSet}, 92*e1997b9aSAndroid Build Coastguard Worker path::Path, 93*e1997b9aSAndroid Build Coastguard Worker sync::{Arc, Condvar, Mutex}, 94*e1997b9aSAndroid Build Coastguard Worker time::{Duration, SystemTime}, 95*e1997b9aSAndroid Build Coastguard Worker }; 96*e1997b9aSAndroid Build Coastguard Worker 97*e1997b9aSAndroid Build Coastguard Worker use TransactionBehavior::Immediate; 98*e1997b9aSAndroid Build Coastguard Worker 99*e1997b9aSAndroid Build Coastguard Worker #[cfg(test)] 100*e1997b9aSAndroid Build Coastguard Worker use tests::random; 101*e1997b9aSAndroid Build Coastguard Worker 102*e1997b9aSAndroid Build Coastguard Worker /// Wrapper for `rusqlite::TransactionBehavior` which includes information about the transaction 103*e1997b9aSAndroid Build Coastguard Worker /// being performed. 104*e1997b9aSAndroid Build Coastguard Worker #[derive(Clone, Copy)] 105*e1997b9aSAndroid Build Coastguard Worker enum TransactionBehavior { 106*e1997b9aSAndroid Build Coastguard Worker Deferred, 107*e1997b9aSAndroid Build Coastguard Worker Immediate(&'static str), 108*e1997b9aSAndroid Build Coastguard Worker } 109*e1997b9aSAndroid Build Coastguard Worker 110*e1997b9aSAndroid Build Coastguard Worker impl From<TransactionBehavior> for rusqlite::TransactionBehavior { from(val: TransactionBehavior) -> Self111*e1997b9aSAndroid Build Coastguard Worker fn from(val: TransactionBehavior) -> Self { 112*e1997b9aSAndroid Build Coastguard Worker match val { 113*e1997b9aSAndroid Build Coastguard Worker TransactionBehavior::Deferred => rusqlite::TransactionBehavior::Deferred, 114*e1997b9aSAndroid Build Coastguard Worker TransactionBehavior::Immediate(_) => rusqlite::TransactionBehavior::Immediate, 115*e1997b9aSAndroid Build Coastguard Worker } 116*e1997b9aSAndroid Build Coastguard Worker } 117*e1997b9aSAndroid Build Coastguard Worker } 118*e1997b9aSAndroid Build Coastguard Worker 119*e1997b9aSAndroid Build Coastguard Worker impl TransactionBehavior { name(&self) -> Option<&'static str>120*e1997b9aSAndroid Build Coastguard Worker fn name(&self) -> Option<&'static str> { 121*e1997b9aSAndroid Build Coastguard Worker match self { 122*e1997b9aSAndroid Build Coastguard Worker TransactionBehavior::Deferred => None, 123*e1997b9aSAndroid Build Coastguard Worker TransactionBehavior::Immediate(v) => Some(v), 124*e1997b9aSAndroid Build Coastguard Worker } 125*e1997b9aSAndroid Build Coastguard Worker } 126*e1997b9aSAndroid Build Coastguard Worker } 127*e1997b9aSAndroid Build Coastguard Worker 128*e1997b9aSAndroid Build Coastguard Worker /// Access information for a key. 129*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)] 130*e1997b9aSAndroid Build Coastguard Worker struct KeyAccessInfo { 131*e1997b9aSAndroid Build Coastguard Worker key_id: i64, 132*e1997b9aSAndroid Build Coastguard Worker descriptor: KeyDescriptor, 133*e1997b9aSAndroid Build Coastguard Worker vector: Option<KeyPermSet>, 134*e1997b9aSAndroid Build Coastguard Worker } 135*e1997b9aSAndroid Build Coastguard Worker 136*e1997b9aSAndroid Build Coastguard Worker /// If the database returns a busy error code, retry after this interval. 137*e1997b9aSAndroid Build Coastguard Worker const DB_BUSY_RETRY_INTERVAL: Duration = Duration::from_micros(500); 138*e1997b9aSAndroid Build Coastguard Worker 139*e1997b9aSAndroid Build Coastguard Worker impl_metadata!( 140*e1997b9aSAndroid Build Coastguard Worker /// A set of metadata for key entries. 141*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Default, Eq, PartialEq)] 142*e1997b9aSAndroid Build Coastguard Worker pub struct KeyMetaData; 143*e1997b9aSAndroid Build Coastguard Worker /// A metadata entry for key entries. 144*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] 145*e1997b9aSAndroid Build Coastguard Worker pub enum KeyMetaEntry { 146*e1997b9aSAndroid Build Coastguard Worker /// Date of the creation of the key entry. 147*e1997b9aSAndroid Build Coastguard Worker CreationDate(DateTime) with accessor creation_date, 148*e1997b9aSAndroid Build Coastguard Worker /// Expiration date for attestation keys. 149*e1997b9aSAndroid Build Coastguard Worker AttestationExpirationDate(DateTime) with accessor attestation_expiration_date, 150*e1997b9aSAndroid Build Coastguard Worker /// CBOR Blob that represents a COSE_Key and associated metadata needed for remote 151*e1997b9aSAndroid Build Coastguard Worker /// provisioning 152*e1997b9aSAndroid Build Coastguard Worker AttestationMacedPublicKey(Vec<u8>) with accessor attestation_maced_public_key, 153*e1997b9aSAndroid Build Coastguard Worker /// Vector representing the raw public key so results from the server can be matched 154*e1997b9aSAndroid Build Coastguard Worker /// to the right entry 155*e1997b9aSAndroid Build Coastguard Worker AttestationRawPubKey(Vec<u8>) with accessor attestation_raw_pub_key, 156*e1997b9aSAndroid Build Coastguard Worker /// SEC1 public key for ECDH encryption 157*e1997b9aSAndroid Build Coastguard Worker Sec1PublicKey(Vec<u8>) with accessor sec1_public_key, 158*e1997b9aSAndroid Build Coastguard Worker // --- ADD NEW META DATA FIELDS HERE --- 159*e1997b9aSAndroid Build Coastguard Worker // For backwards compatibility add new entries only to 160*e1997b9aSAndroid Build Coastguard Worker // end of this list and above this comment. 161*e1997b9aSAndroid Build Coastguard Worker }; 162*e1997b9aSAndroid Build Coastguard Worker ); 163*e1997b9aSAndroid Build Coastguard Worker 164*e1997b9aSAndroid Build Coastguard Worker impl KeyMetaData { load_from_db(key_id: i64, tx: &Transaction) -> Result<Self>165*e1997b9aSAndroid Build Coastguard Worker fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> { 166*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 167*e1997b9aSAndroid Build Coastguard Worker .prepare( 168*e1997b9aSAndroid Build Coastguard Worker "SELECT tag, data from persistent.keymetadata 169*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ?;", 170*e1997b9aSAndroid Build Coastguard Worker ) 171*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeyMetaData::load_from_db: prepare statement failed."))?; 172*e1997b9aSAndroid Build Coastguard Worker 173*e1997b9aSAndroid Build Coastguard Worker let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default(); 174*e1997b9aSAndroid Build Coastguard Worker 175*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 176*e1997b9aSAndroid Build Coastguard Worker .query(params![key_id]) 177*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeyMetaData::load_from_db: query failed."))?; 178*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 179*e1997b9aSAndroid Build Coastguard Worker let db_tag: i64 = row.get(0).context("Failed to read tag.")?; 180*e1997b9aSAndroid Build Coastguard Worker metadata.insert( 181*e1997b9aSAndroid Build Coastguard Worker db_tag, 182*e1997b9aSAndroid Build Coastguard Worker KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, row)) 183*e1997b9aSAndroid Build Coastguard Worker .context("Failed to read KeyMetaEntry.")?, 184*e1997b9aSAndroid Build Coastguard Worker ); 185*e1997b9aSAndroid Build Coastguard Worker Ok(()) 186*e1997b9aSAndroid Build Coastguard Worker }) 187*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeyMetaData::load_from_db."))?; 188*e1997b9aSAndroid Build Coastguard Worker 189*e1997b9aSAndroid Build Coastguard Worker Ok(Self { data: metadata }) 190*e1997b9aSAndroid Build Coastguard Worker } 191*e1997b9aSAndroid Build Coastguard Worker store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()>192*e1997b9aSAndroid Build Coastguard Worker fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> { 193*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 194*e1997b9aSAndroid Build Coastguard Worker .prepare( 195*e1997b9aSAndroid Build Coastguard Worker "INSERT or REPLACE INTO persistent.keymetadata (keyentryid, tag, data) 196*e1997b9aSAndroid Build Coastguard Worker VALUES (?, ?, ?);", 197*e1997b9aSAndroid Build Coastguard Worker ) 198*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeyMetaData::store_in_db: Failed to prepare statement."))?; 199*e1997b9aSAndroid Build Coastguard Worker 200*e1997b9aSAndroid Build Coastguard Worker let iter = self.data.iter(); 201*e1997b9aSAndroid Build Coastguard Worker for (tag, entry) in iter { 202*e1997b9aSAndroid Build Coastguard Worker stmt.insert(params![key_id, tag, entry,]).with_context(|| { 203*e1997b9aSAndroid Build Coastguard Worker ks_err!("KeyMetaData::store_in_db: Failed to insert {:?}", entry) 204*e1997b9aSAndroid Build Coastguard Worker })?; 205*e1997b9aSAndroid Build Coastguard Worker } 206*e1997b9aSAndroid Build Coastguard Worker Ok(()) 207*e1997b9aSAndroid Build Coastguard Worker } 208*e1997b9aSAndroid Build Coastguard Worker } 209*e1997b9aSAndroid Build Coastguard Worker 210*e1997b9aSAndroid Build Coastguard Worker impl_metadata!( 211*e1997b9aSAndroid Build Coastguard Worker /// A set of metadata for key blobs. 212*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Default, Eq, PartialEq)] 213*e1997b9aSAndroid Build Coastguard Worker pub struct BlobMetaData; 214*e1997b9aSAndroid Build Coastguard Worker /// A metadata entry for key blobs. 215*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] 216*e1997b9aSAndroid Build Coastguard Worker pub enum BlobMetaEntry { 217*e1997b9aSAndroid Build Coastguard Worker /// If present, indicates that the blob is encrypted with another key or a key derived 218*e1997b9aSAndroid Build Coastguard Worker /// from a password. 219*e1997b9aSAndroid Build Coastguard Worker EncryptedBy(EncryptedBy) with accessor encrypted_by, 220*e1997b9aSAndroid Build Coastguard Worker /// If the blob is password encrypted this field is set to the 221*e1997b9aSAndroid Build Coastguard Worker /// salt used for the key derivation. 222*e1997b9aSAndroid Build Coastguard Worker Salt(Vec<u8>) with accessor salt, 223*e1997b9aSAndroid Build Coastguard Worker /// If the blob is encrypted, this field is set to the initialization vector. 224*e1997b9aSAndroid Build Coastguard Worker Iv(Vec<u8>) with accessor iv, 225*e1997b9aSAndroid Build Coastguard Worker /// If the blob is encrypted, this field holds the AEAD TAG. 226*e1997b9aSAndroid Build Coastguard Worker AeadTag(Vec<u8>) with accessor aead_tag, 227*e1997b9aSAndroid Build Coastguard Worker /// The uuid of the owning KeyMint instance. 228*e1997b9aSAndroid Build Coastguard Worker KmUuid(Uuid) with accessor km_uuid, 229*e1997b9aSAndroid Build Coastguard Worker /// If the key is ECDH encrypted, this is the ephemeral public key 230*e1997b9aSAndroid Build Coastguard Worker PublicKey(Vec<u8>) with accessor public_key, 231*e1997b9aSAndroid Build Coastguard Worker /// If the key is encrypted with a MaxBootLevel key, this is the boot level 232*e1997b9aSAndroid Build Coastguard Worker /// of that key 233*e1997b9aSAndroid Build Coastguard Worker MaxBootLevel(i32) with accessor max_boot_level, 234*e1997b9aSAndroid Build Coastguard Worker // --- ADD NEW META DATA FIELDS HERE --- 235*e1997b9aSAndroid Build Coastguard Worker // For backwards compatibility add new entries only to 236*e1997b9aSAndroid Build Coastguard Worker // end of this list and above this comment. 237*e1997b9aSAndroid Build Coastguard Worker }; 238*e1997b9aSAndroid Build Coastguard Worker ); 239*e1997b9aSAndroid Build Coastguard Worker 240*e1997b9aSAndroid Build Coastguard Worker impl BlobMetaData { load_from_db(blob_id: i64, tx: &Transaction) -> Result<Self>241*e1997b9aSAndroid Build Coastguard Worker fn load_from_db(blob_id: i64, tx: &Transaction) -> Result<Self> { 242*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 243*e1997b9aSAndroid Build Coastguard Worker .prepare( 244*e1997b9aSAndroid Build Coastguard Worker "SELECT tag, data from persistent.blobmetadata 245*e1997b9aSAndroid Build Coastguard Worker WHERE blobentryid = ?;", 246*e1997b9aSAndroid Build Coastguard Worker ) 247*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("BlobMetaData::load_from_db: prepare statement failed."))?; 248*e1997b9aSAndroid Build Coastguard Worker 249*e1997b9aSAndroid Build Coastguard Worker let mut metadata: HashMap<i64, BlobMetaEntry> = Default::default(); 250*e1997b9aSAndroid Build Coastguard Worker 251*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt.query(params![blob_id]).context(ks_err!("query failed."))?; 252*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 253*e1997b9aSAndroid Build Coastguard Worker let db_tag: i64 = row.get(0).context("Failed to read tag.")?; 254*e1997b9aSAndroid Build Coastguard Worker metadata.insert( 255*e1997b9aSAndroid Build Coastguard Worker db_tag, 256*e1997b9aSAndroid Build Coastguard Worker BlobMetaEntry::new_from_sql(db_tag, &SqlField::new(1, row)) 257*e1997b9aSAndroid Build Coastguard Worker .context("Failed to read BlobMetaEntry.")?, 258*e1997b9aSAndroid Build Coastguard Worker ); 259*e1997b9aSAndroid Build Coastguard Worker Ok(()) 260*e1997b9aSAndroid Build Coastguard Worker }) 261*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("BlobMetaData::load_from_db"))?; 262*e1997b9aSAndroid Build Coastguard Worker 263*e1997b9aSAndroid Build Coastguard Worker Ok(Self { data: metadata }) 264*e1997b9aSAndroid Build Coastguard Worker } 265*e1997b9aSAndroid Build Coastguard Worker store_in_db(&self, blob_id: i64, tx: &Transaction) -> Result<()>266*e1997b9aSAndroid Build Coastguard Worker fn store_in_db(&self, blob_id: i64, tx: &Transaction) -> Result<()> { 267*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 268*e1997b9aSAndroid Build Coastguard Worker .prepare( 269*e1997b9aSAndroid Build Coastguard Worker "INSERT or REPLACE INTO persistent.blobmetadata (blobentryid, tag, data) 270*e1997b9aSAndroid Build Coastguard Worker VALUES (?, ?, ?);", 271*e1997b9aSAndroid Build Coastguard Worker ) 272*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("BlobMetaData::store_in_db: Failed to prepare statement.",))?; 273*e1997b9aSAndroid Build Coastguard Worker 274*e1997b9aSAndroid Build Coastguard Worker let iter = self.data.iter(); 275*e1997b9aSAndroid Build Coastguard Worker for (tag, entry) in iter { 276*e1997b9aSAndroid Build Coastguard Worker stmt.insert(params![blob_id, tag, entry,]).with_context(|| { 277*e1997b9aSAndroid Build Coastguard Worker ks_err!("BlobMetaData::store_in_db: Failed to insert {:?}", entry) 278*e1997b9aSAndroid Build Coastguard Worker })?; 279*e1997b9aSAndroid Build Coastguard Worker } 280*e1997b9aSAndroid Build Coastguard Worker Ok(()) 281*e1997b9aSAndroid Build Coastguard Worker } 282*e1997b9aSAndroid Build Coastguard Worker } 283*e1997b9aSAndroid Build Coastguard Worker 284*e1997b9aSAndroid Build Coastguard Worker /// Indicates the type of the keyentry. 285*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] 286*e1997b9aSAndroid Build Coastguard Worker pub enum KeyType { 287*e1997b9aSAndroid Build Coastguard Worker /// This is a client key type. These keys are created or imported through the Keystore 2.0 288*e1997b9aSAndroid Build Coastguard Worker /// AIDL interface android.system.keystore2. 289*e1997b9aSAndroid Build Coastguard Worker Client, 290*e1997b9aSAndroid Build Coastguard Worker /// This is a super key type. These keys are created by keystore itself and used to encrypt 291*e1997b9aSAndroid Build Coastguard Worker /// other key blobs to provide LSKF binding. 292*e1997b9aSAndroid Build Coastguard Worker Super, 293*e1997b9aSAndroid Build Coastguard Worker } 294*e1997b9aSAndroid Build Coastguard Worker 295*e1997b9aSAndroid Build Coastguard Worker impl ToSql for KeyType { to_sql(&self) -> rusqlite::Result<ToSqlOutput>296*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 297*e1997b9aSAndroid Build Coastguard Worker Ok(ToSqlOutput::Owned(Value::Integer(match self { 298*e1997b9aSAndroid Build Coastguard Worker KeyType::Client => 0, 299*e1997b9aSAndroid Build Coastguard Worker KeyType::Super => 1, 300*e1997b9aSAndroid Build Coastguard Worker }))) 301*e1997b9aSAndroid Build Coastguard Worker } 302*e1997b9aSAndroid Build Coastguard Worker } 303*e1997b9aSAndroid Build Coastguard Worker 304*e1997b9aSAndroid Build Coastguard Worker impl FromSql for KeyType { column_result(value: ValueRef) -> FromSqlResult<Self>305*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 306*e1997b9aSAndroid Build Coastguard Worker match i64::column_result(value)? { 307*e1997b9aSAndroid Build Coastguard Worker 0 => Ok(KeyType::Client), 308*e1997b9aSAndroid Build Coastguard Worker 1 => Ok(KeyType::Super), 309*e1997b9aSAndroid Build Coastguard Worker v => Err(FromSqlError::OutOfRange(v)), 310*e1997b9aSAndroid Build Coastguard Worker } 311*e1997b9aSAndroid Build Coastguard Worker } 312*e1997b9aSAndroid Build Coastguard Worker } 313*e1997b9aSAndroid Build Coastguard Worker 314*e1997b9aSAndroid Build Coastguard Worker /// Uuid representation that can be stored in the database. 315*e1997b9aSAndroid Build Coastguard Worker /// Right now it can only be initialized from SecurityLevel. 316*e1997b9aSAndroid Build Coastguard Worker /// Once KeyMint provides a UUID type a corresponding From impl shall be added. 317*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] 318*e1997b9aSAndroid Build Coastguard Worker pub struct Uuid([u8; 16]); 319*e1997b9aSAndroid Build Coastguard Worker 320*e1997b9aSAndroid Build Coastguard Worker impl Deref for Uuid { 321*e1997b9aSAndroid Build Coastguard Worker type Target = [u8; 16]; 322*e1997b9aSAndroid Build Coastguard Worker deref(&self) -> &Self::Target323*e1997b9aSAndroid Build Coastguard Worker fn deref(&self) -> &Self::Target { 324*e1997b9aSAndroid Build Coastguard Worker &self.0 325*e1997b9aSAndroid Build Coastguard Worker } 326*e1997b9aSAndroid Build Coastguard Worker } 327*e1997b9aSAndroid Build Coastguard Worker 328*e1997b9aSAndroid Build Coastguard Worker impl From<SecurityLevel> for Uuid { from(sec_level: SecurityLevel) -> Self329*e1997b9aSAndroid Build Coastguard Worker fn from(sec_level: SecurityLevel) -> Self { 330*e1997b9aSAndroid Build Coastguard Worker Self((sec_level.0 as u128).to_be_bytes()) 331*e1997b9aSAndroid Build Coastguard Worker } 332*e1997b9aSAndroid Build Coastguard Worker } 333*e1997b9aSAndroid Build Coastguard Worker 334*e1997b9aSAndroid Build Coastguard Worker impl ToSql for Uuid { to_sql(&self) -> rusqlite::Result<ToSqlOutput>335*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 336*e1997b9aSAndroid Build Coastguard Worker self.0.to_sql() 337*e1997b9aSAndroid Build Coastguard Worker } 338*e1997b9aSAndroid Build Coastguard Worker } 339*e1997b9aSAndroid Build Coastguard Worker 340*e1997b9aSAndroid Build Coastguard Worker impl FromSql for Uuid { column_result(value: ValueRef<'_>) -> FromSqlResult<Self>341*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> { 342*e1997b9aSAndroid Build Coastguard Worker let blob = Vec::<u8>::column_result(value)?; 343*e1997b9aSAndroid Build Coastguard Worker if blob.len() != 16 { 344*e1997b9aSAndroid Build Coastguard Worker return Err(FromSqlError::OutOfRange(blob.len() as i64)); 345*e1997b9aSAndroid Build Coastguard Worker } 346*e1997b9aSAndroid Build Coastguard Worker let mut arr = [0u8; 16]; 347*e1997b9aSAndroid Build Coastguard Worker arr.copy_from_slice(&blob); 348*e1997b9aSAndroid Build Coastguard Worker Ok(Self(arr)) 349*e1997b9aSAndroid Build Coastguard Worker } 350*e1997b9aSAndroid Build Coastguard Worker } 351*e1997b9aSAndroid Build Coastguard Worker 352*e1997b9aSAndroid Build Coastguard Worker /// Key entries that are not associated with any KeyMint instance, such as pure certificate 353*e1997b9aSAndroid Build Coastguard Worker /// entries are associated with this UUID. 354*e1997b9aSAndroid Build Coastguard Worker pub static KEYSTORE_UUID: Uuid = Uuid([ 355*e1997b9aSAndroid Build Coastguard Worker 0x41, 0xe3, 0xb9, 0xce, 0x27, 0x58, 0x4e, 0x91, 0xbc, 0xfd, 0xa5, 0x5d, 0x91, 0x85, 0xab, 0x11, 356*e1997b9aSAndroid Build Coastguard Worker ]); 357*e1997b9aSAndroid Build Coastguard Worker 358*e1997b9aSAndroid Build Coastguard Worker /// Indicates how the sensitive part of this key blob is encrypted. 359*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] 360*e1997b9aSAndroid Build Coastguard Worker pub enum EncryptedBy { 361*e1997b9aSAndroid Build Coastguard Worker /// The keyblob is encrypted by a user password. 362*e1997b9aSAndroid Build Coastguard Worker /// In the database this variant is represented as NULL. 363*e1997b9aSAndroid Build Coastguard Worker Password, 364*e1997b9aSAndroid Build Coastguard Worker /// The keyblob is encrypted by another key with wrapped key id. 365*e1997b9aSAndroid Build Coastguard Worker /// In the database this variant is represented as non NULL value 366*e1997b9aSAndroid Build Coastguard Worker /// that is convertible to i64, typically NUMERIC. 367*e1997b9aSAndroid Build Coastguard Worker KeyId(i64), 368*e1997b9aSAndroid Build Coastguard Worker } 369*e1997b9aSAndroid Build Coastguard Worker 370*e1997b9aSAndroid Build Coastguard Worker impl ToSql for EncryptedBy { to_sql(&self) -> rusqlite::Result<ToSqlOutput>371*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 372*e1997b9aSAndroid Build Coastguard Worker match self { 373*e1997b9aSAndroid Build Coastguard Worker Self::Password => Ok(ToSqlOutput::Owned(Value::Null)), 374*e1997b9aSAndroid Build Coastguard Worker Self::KeyId(id) => id.to_sql(), 375*e1997b9aSAndroid Build Coastguard Worker } 376*e1997b9aSAndroid Build Coastguard Worker } 377*e1997b9aSAndroid Build Coastguard Worker } 378*e1997b9aSAndroid Build Coastguard Worker 379*e1997b9aSAndroid Build Coastguard Worker impl FromSql for EncryptedBy { column_result(value: ValueRef) -> FromSqlResult<Self>380*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 381*e1997b9aSAndroid Build Coastguard Worker match value { 382*e1997b9aSAndroid Build Coastguard Worker ValueRef::Null => Ok(Self::Password), 383*e1997b9aSAndroid Build Coastguard Worker _ => Ok(Self::KeyId(i64::column_result(value)?)), 384*e1997b9aSAndroid Build Coastguard Worker } 385*e1997b9aSAndroid Build Coastguard Worker } 386*e1997b9aSAndroid Build Coastguard Worker } 387*e1997b9aSAndroid Build Coastguard Worker 388*e1997b9aSAndroid Build Coastguard Worker /// A database representation of wall clock time. DateTime stores unix epoch time as 389*e1997b9aSAndroid Build Coastguard Worker /// i64 in milliseconds. 390*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] 391*e1997b9aSAndroid Build Coastguard Worker pub struct DateTime(i64); 392*e1997b9aSAndroid Build Coastguard Worker 393*e1997b9aSAndroid Build Coastguard Worker /// Error type returned when creating DateTime or converting it from and to 394*e1997b9aSAndroid Build Coastguard Worker /// SystemTime. 395*e1997b9aSAndroid Build Coastguard Worker #[derive(thiserror::Error, Debug)] 396*e1997b9aSAndroid Build Coastguard Worker pub enum DateTimeError { 397*e1997b9aSAndroid Build Coastguard Worker /// This is returned when SystemTime and Duration computations fail. 398*e1997b9aSAndroid Build Coastguard Worker #[error(transparent)] 399*e1997b9aSAndroid Build Coastguard Worker SystemTimeError(#[from] SystemTimeError), 400*e1997b9aSAndroid Build Coastguard Worker 401*e1997b9aSAndroid Build Coastguard Worker /// This is returned when type conversions fail. 402*e1997b9aSAndroid Build Coastguard Worker #[error(transparent)] 403*e1997b9aSAndroid Build Coastguard Worker TypeConversion(#[from] std::num::TryFromIntError), 404*e1997b9aSAndroid Build Coastguard Worker 405*e1997b9aSAndroid Build Coastguard Worker /// This is returned when checked time arithmetic failed. 406*e1997b9aSAndroid Build Coastguard Worker #[error("Time arithmetic failed.")] 407*e1997b9aSAndroid Build Coastguard Worker TimeArithmetic, 408*e1997b9aSAndroid Build Coastguard Worker } 409*e1997b9aSAndroid Build Coastguard Worker 410*e1997b9aSAndroid Build Coastguard Worker impl DateTime { 411*e1997b9aSAndroid Build Coastguard Worker /// Constructs a new DateTime object denoting the current time. This may fail during 412*e1997b9aSAndroid Build Coastguard Worker /// conversion to unix epoch time and during conversion to the internal i64 representation. now() -> Result<Self, DateTimeError>413*e1997b9aSAndroid Build Coastguard Worker pub fn now() -> Result<Self, DateTimeError> { 414*e1997b9aSAndroid Build Coastguard Worker Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?)) 415*e1997b9aSAndroid Build Coastguard Worker } 416*e1997b9aSAndroid Build Coastguard Worker 417*e1997b9aSAndroid Build Coastguard Worker /// Constructs a new DateTime object from milliseconds. from_millis_epoch(millis: i64) -> Self418*e1997b9aSAndroid Build Coastguard Worker pub fn from_millis_epoch(millis: i64) -> Self { 419*e1997b9aSAndroid Build Coastguard Worker Self(millis) 420*e1997b9aSAndroid Build Coastguard Worker } 421*e1997b9aSAndroid Build Coastguard Worker 422*e1997b9aSAndroid Build Coastguard Worker /// Returns unix epoch time in milliseconds. to_millis_epoch(self) -> i64423*e1997b9aSAndroid Build Coastguard Worker pub fn to_millis_epoch(self) -> i64 { 424*e1997b9aSAndroid Build Coastguard Worker self.0 425*e1997b9aSAndroid Build Coastguard Worker } 426*e1997b9aSAndroid Build Coastguard Worker } 427*e1997b9aSAndroid Build Coastguard Worker 428*e1997b9aSAndroid Build Coastguard Worker impl ToSql for DateTime { to_sql(&self) -> rusqlite::Result<ToSqlOutput>429*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 430*e1997b9aSAndroid Build Coastguard Worker Ok(ToSqlOutput::Owned(Value::Integer(self.0))) 431*e1997b9aSAndroid Build Coastguard Worker } 432*e1997b9aSAndroid Build Coastguard Worker } 433*e1997b9aSAndroid Build Coastguard Worker 434*e1997b9aSAndroid Build Coastguard Worker impl FromSql for DateTime { column_result(value: ValueRef) -> FromSqlResult<Self>435*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 436*e1997b9aSAndroid Build Coastguard Worker Ok(Self(i64::column_result(value)?)) 437*e1997b9aSAndroid Build Coastguard Worker } 438*e1997b9aSAndroid Build Coastguard Worker } 439*e1997b9aSAndroid Build Coastguard Worker 440*e1997b9aSAndroid Build Coastguard Worker impl TryInto<SystemTime> for DateTime { 441*e1997b9aSAndroid Build Coastguard Worker type Error = DateTimeError; 442*e1997b9aSAndroid Build Coastguard Worker try_into(self) -> Result<SystemTime, Self::Error>443*e1997b9aSAndroid Build Coastguard Worker fn try_into(self) -> Result<SystemTime, Self::Error> { 444*e1997b9aSAndroid Build Coastguard Worker // We want to construct a SystemTime representation equivalent to self, denoting 445*e1997b9aSAndroid Build Coastguard Worker // a point in time THEN, but we cannot set the time directly. We can only construct 446*e1997b9aSAndroid Build Coastguard Worker // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW, 447*e1997b9aSAndroid Build Coastguard Worker // and between EPOCH and THEN. With this common reference we can construct the 448*e1997b9aSAndroid Build Coastguard Worker // duration between NOW and THEN which we can add to our SystemTime representation 449*e1997b9aSAndroid Build Coastguard Worker // of NOW to get a SystemTime representation of THEN. 450*e1997b9aSAndroid Build Coastguard Worker // Durations can only be positive, thus the if statement below. 451*e1997b9aSAndroid Build Coastguard Worker let now = SystemTime::now(); 452*e1997b9aSAndroid Build Coastguard Worker let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?; 453*e1997b9aSAndroid Build Coastguard Worker let then_epoch = Duration::from_millis(self.0.try_into()?); 454*e1997b9aSAndroid Build Coastguard Worker Ok(if now_epoch > then_epoch { 455*e1997b9aSAndroid Build Coastguard Worker // then = now - (now_epoch - then_epoch) 456*e1997b9aSAndroid Build Coastguard Worker now_epoch 457*e1997b9aSAndroid Build Coastguard Worker .checked_sub(then_epoch) 458*e1997b9aSAndroid Build Coastguard Worker .and_then(|d| now.checked_sub(d)) 459*e1997b9aSAndroid Build Coastguard Worker .ok_or(DateTimeError::TimeArithmetic)? 460*e1997b9aSAndroid Build Coastguard Worker } else { 461*e1997b9aSAndroid Build Coastguard Worker // then = now + (then_epoch - now_epoch) 462*e1997b9aSAndroid Build Coastguard Worker then_epoch 463*e1997b9aSAndroid Build Coastguard Worker .checked_sub(now_epoch) 464*e1997b9aSAndroid Build Coastguard Worker .and_then(|d| now.checked_add(d)) 465*e1997b9aSAndroid Build Coastguard Worker .ok_or(DateTimeError::TimeArithmetic)? 466*e1997b9aSAndroid Build Coastguard Worker }) 467*e1997b9aSAndroid Build Coastguard Worker } 468*e1997b9aSAndroid Build Coastguard Worker } 469*e1997b9aSAndroid Build Coastguard Worker 470*e1997b9aSAndroid Build Coastguard Worker impl TryFrom<SystemTime> for DateTime { 471*e1997b9aSAndroid Build Coastguard Worker type Error = DateTimeError; 472*e1997b9aSAndroid Build Coastguard Worker try_from(t: SystemTime) -> Result<Self, Self::Error>473*e1997b9aSAndroid Build Coastguard Worker fn try_from(t: SystemTime) -> Result<Self, Self::Error> { 474*e1997b9aSAndroid Build Coastguard Worker Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?)) 475*e1997b9aSAndroid Build Coastguard Worker } 476*e1997b9aSAndroid Build Coastguard Worker } 477*e1997b9aSAndroid Build Coastguard Worker 478*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] 479*e1997b9aSAndroid Build Coastguard Worker enum KeyLifeCycle { 480*e1997b9aSAndroid Build Coastguard Worker /// Existing keys have a key ID but are not fully populated yet. 481*e1997b9aSAndroid Build Coastguard Worker /// This is a transient state. If Keystore finds any such keys when it starts up, it must move 482*e1997b9aSAndroid Build Coastguard Worker /// them to Unreferenced for garbage collection. 483*e1997b9aSAndroid Build Coastguard Worker Existing, 484*e1997b9aSAndroid Build Coastguard Worker /// A live key is fully populated and usable by clients. 485*e1997b9aSAndroid Build Coastguard Worker Live, 486*e1997b9aSAndroid Build Coastguard Worker /// An unreferenced key is scheduled for garbage collection. 487*e1997b9aSAndroid Build Coastguard Worker Unreferenced, 488*e1997b9aSAndroid Build Coastguard Worker } 489*e1997b9aSAndroid Build Coastguard Worker 490*e1997b9aSAndroid Build Coastguard Worker impl ToSql for KeyLifeCycle { to_sql(&self) -> rusqlite::Result<ToSqlOutput>491*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 492*e1997b9aSAndroid Build Coastguard Worker match self { 493*e1997b9aSAndroid Build Coastguard Worker Self::Existing => Ok(ToSqlOutput::Owned(Value::Integer(0))), 494*e1997b9aSAndroid Build Coastguard Worker Self::Live => Ok(ToSqlOutput::Owned(Value::Integer(1))), 495*e1997b9aSAndroid Build Coastguard Worker Self::Unreferenced => Ok(ToSqlOutput::Owned(Value::Integer(2))), 496*e1997b9aSAndroid Build Coastguard Worker } 497*e1997b9aSAndroid Build Coastguard Worker } 498*e1997b9aSAndroid Build Coastguard Worker } 499*e1997b9aSAndroid Build Coastguard Worker 500*e1997b9aSAndroid Build Coastguard Worker impl FromSql for KeyLifeCycle { column_result(value: ValueRef) -> FromSqlResult<Self>501*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 502*e1997b9aSAndroid Build Coastguard Worker match i64::column_result(value)? { 503*e1997b9aSAndroid Build Coastguard Worker 0 => Ok(KeyLifeCycle::Existing), 504*e1997b9aSAndroid Build Coastguard Worker 1 => Ok(KeyLifeCycle::Live), 505*e1997b9aSAndroid Build Coastguard Worker 2 => Ok(KeyLifeCycle::Unreferenced), 506*e1997b9aSAndroid Build Coastguard Worker v => Err(FromSqlError::OutOfRange(v)), 507*e1997b9aSAndroid Build Coastguard Worker } 508*e1997b9aSAndroid Build Coastguard Worker } 509*e1997b9aSAndroid Build Coastguard Worker } 510*e1997b9aSAndroid Build Coastguard Worker 511*e1997b9aSAndroid Build Coastguard Worker /// Current state of a `blobentry` row. 512*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Default)] 513*e1997b9aSAndroid Build Coastguard Worker enum BlobState { 514*e1997b9aSAndroid Build Coastguard Worker #[default] 515*e1997b9aSAndroid Build Coastguard Worker /// Current blobentry (of its `subcomponent_type`) for the associated key. 516*e1997b9aSAndroid Build Coastguard Worker Current, 517*e1997b9aSAndroid Build Coastguard Worker /// Blobentry that is no longer the current blob (of its `subcomponent_type`) for the associated 518*e1997b9aSAndroid Build Coastguard Worker /// key. 519*e1997b9aSAndroid Build Coastguard Worker Superseded, 520*e1997b9aSAndroid Build Coastguard Worker /// Blobentry for a key that no longer exists. 521*e1997b9aSAndroid Build Coastguard Worker Orphaned, 522*e1997b9aSAndroid Build Coastguard Worker } 523*e1997b9aSAndroid Build Coastguard Worker 524*e1997b9aSAndroid Build Coastguard Worker impl ToSql for BlobState { to_sql(&self) -> rusqlite::Result<ToSqlOutput>525*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 526*e1997b9aSAndroid Build Coastguard Worker match self { 527*e1997b9aSAndroid Build Coastguard Worker Self::Current => Ok(ToSqlOutput::Owned(Value::Integer(0))), 528*e1997b9aSAndroid Build Coastguard Worker Self::Superseded => Ok(ToSqlOutput::Owned(Value::Integer(1))), 529*e1997b9aSAndroid Build Coastguard Worker Self::Orphaned => Ok(ToSqlOutput::Owned(Value::Integer(2))), 530*e1997b9aSAndroid Build Coastguard Worker } 531*e1997b9aSAndroid Build Coastguard Worker } 532*e1997b9aSAndroid Build Coastguard Worker } 533*e1997b9aSAndroid Build Coastguard Worker 534*e1997b9aSAndroid Build Coastguard Worker impl FromSql for BlobState { column_result(value: ValueRef) -> FromSqlResult<Self>535*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 536*e1997b9aSAndroid Build Coastguard Worker match i64::column_result(value)? { 537*e1997b9aSAndroid Build Coastguard Worker 0 => Ok(Self::Current), 538*e1997b9aSAndroid Build Coastguard Worker 1 => Ok(Self::Superseded), 539*e1997b9aSAndroid Build Coastguard Worker 2 => Ok(Self::Orphaned), 540*e1997b9aSAndroid Build Coastguard Worker v => Err(FromSqlError::OutOfRange(v)), 541*e1997b9aSAndroid Build Coastguard Worker } 542*e1997b9aSAndroid Build Coastguard Worker } 543*e1997b9aSAndroid Build Coastguard Worker } 544*e1997b9aSAndroid Build Coastguard Worker 545*e1997b9aSAndroid Build Coastguard Worker /// Keys have a KeyMint blob component and optional public certificate and 546*e1997b9aSAndroid Build Coastguard Worker /// certificate chain components. 547*e1997b9aSAndroid Build Coastguard Worker /// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry` 548*e1997b9aSAndroid Build Coastguard Worker /// which components shall be loaded from the database if present. 549*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] 550*e1997b9aSAndroid Build Coastguard Worker pub struct KeyEntryLoadBits(u32); 551*e1997b9aSAndroid Build Coastguard Worker 552*e1997b9aSAndroid Build Coastguard Worker impl KeyEntryLoadBits { 553*e1997b9aSAndroid Build Coastguard Worker /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded. 554*e1997b9aSAndroid Build Coastguard Worker pub const NONE: KeyEntryLoadBits = Self(0); 555*e1997b9aSAndroid Build Coastguard Worker /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded. 556*e1997b9aSAndroid Build Coastguard Worker pub const KM: KeyEntryLoadBits = Self(1); 557*e1997b9aSAndroid Build Coastguard Worker /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded. 558*e1997b9aSAndroid Build Coastguard Worker pub const PUBLIC: KeyEntryLoadBits = Self(2); 559*e1997b9aSAndroid Build Coastguard Worker /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded. 560*e1997b9aSAndroid Build Coastguard Worker pub const BOTH: KeyEntryLoadBits = Self(3); 561*e1997b9aSAndroid Build Coastguard Worker 562*e1997b9aSAndroid Build Coastguard Worker /// Returns true if this object indicates that the public components shall be loaded. load_public(&self) -> bool563*e1997b9aSAndroid Build Coastguard Worker pub const fn load_public(&self) -> bool { 564*e1997b9aSAndroid Build Coastguard Worker self.0 & Self::PUBLIC.0 != 0 565*e1997b9aSAndroid Build Coastguard Worker } 566*e1997b9aSAndroid Build Coastguard Worker 567*e1997b9aSAndroid Build Coastguard Worker /// Returns true if the object indicates that the KeyMint component shall be loaded. load_km(&self) -> bool568*e1997b9aSAndroid Build Coastguard Worker pub const fn load_km(&self) -> bool { 569*e1997b9aSAndroid Build Coastguard Worker self.0 & Self::KM.0 != 0 570*e1997b9aSAndroid Build Coastguard Worker } 571*e1997b9aSAndroid Build Coastguard Worker } 572*e1997b9aSAndroid Build Coastguard Worker 573*e1997b9aSAndroid Build Coastguard Worker static KEY_ID_LOCK: LazyLock<KeyIdLockDb> = LazyLock::new(KeyIdLockDb::new); 574*e1997b9aSAndroid Build Coastguard Worker 575*e1997b9aSAndroid Build Coastguard Worker struct KeyIdLockDb { 576*e1997b9aSAndroid Build Coastguard Worker locked_keys: Mutex<HashSet<i64>>, 577*e1997b9aSAndroid Build Coastguard Worker cond_var: Condvar, 578*e1997b9aSAndroid Build Coastguard Worker } 579*e1997b9aSAndroid Build Coastguard Worker 580*e1997b9aSAndroid Build Coastguard Worker /// A locked key. While a guard exists for a given key id, the same key cannot be loaded 581*e1997b9aSAndroid Build Coastguard Worker /// from the database a second time. Most functions manipulating the key blob database 582*e1997b9aSAndroid Build Coastguard Worker /// require a KeyIdGuard. 583*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)] 584*e1997b9aSAndroid Build Coastguard Worker pub struct KeyIdGuard(i64); 585*e1997b9aSAndroid Build Coastguard Worker 586*e1997b9aSAndroid Build Coastguard Worker impl KeyIdLockDb { new() -> Self587*e1997b9aSAndroid Build Coastguard Worker fn new() -> Self { 588*e1997b9aSAndroid Build Coastguard Worker Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() } 589*e1997b9aSAndroid Build Coastguard Worker } 590*e1997b9aSAndroid Build Coastguard Worker 591*e1997b9aSAndroid Build Coastguard Worker /// This function blocks until an exclusive lock for the given key entry id can 592*e1997b9aSAndroid Build Coastguard Worker /// be acquired. It returns a guard object, that represents the lifecycle of the 593*e1997b9aSAndroid Build Coastguard Worker /// acquired lock. get(&self, key_id: i64) -> KeyIdGuard594*e1997b9aSAndroid Build Coastguard Worker fn get(&self, key_id: i64) -> KeyIdGuard { 595*e1997b9aSAndroid Build Coastguard Worker let mut locked_keys = self.locked_keys.lock().unwrap(); 596*e1997b9aSAndroid Build Coastguard Worker while locked_keys.contains(&key_id) { 597*e1997b9aSAndroid Build Coastguard Worker locked_keys = self.cond_var.wait(locked_keys).unwrap(); 598*e1997b9aSAndroid Build Coastguard Worker } 599*e1997b9aSAndroid Build Coastguard Worker locked_keys.insert(key_id); 600*e1997b9aSAndroid Build Coastguard Worker KeyIdGuard(key_id) 601*e1997b9aSAndroid Build Coastguard Worker } 602*e1997b9aSAndroid Build Coastguard Worker 603*e1997b9aSAndroid Build Coastguard Worker /// This function attempts to acquire an exclusive lock on a given key id. If the 604*e1997b9aSAndroid Build Coastguard Worker /// given key id is already taken the function returns None immediately. If a lock 605*e1997b9aSAndroid Build Coastguard Worker /// can be acquired this function returns a guard object, that represents the 606*e1997b9aSAndroid Build Coastguard Worker /// lifecycle of the acquired lock. try_get(&self, key_id: i64) -> Option<KeyIdGuard>607*e1997b9aSAndroid Build Coastguard Worker fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> { 608*e1997b9aSAndroid Build Coastguard Worker let mut locked_keys = self.locked_keys.lock().unwrap(); 609*e1997b9aSAndroid Build Coastguard Worker if locked_keys.insert(key_id) { 610*e1997b9aSAndroid Build Coastguard Worker Some(KeyIdGuard(key_id)) 611*e1997b9aSAndroid Build Coastguard Worker } else { 612*e1997b9aSAndroid Build Coastguard Worker None 613*e1997b9aSAndroid Build Coastguard Worker } 614*e1997b9aSAndroid Build Coastguard Worker } 615*e1997b9aSAndroid Build Coastguard Worker } 616*e1997b9aSAndroid Build Coastguard Worker 617*e1997b9aSAndroid Build Coastguard Worker impl KeyIdGuard { 618*e1997b9aSAndroid Build Coastguard Worker /// Get the numeric key id of the locked key. id(&self) -> i64619*e1997b9aSAndroid Build Coastguard Worker pub fn id(&self) -> i64 { 620*e1997b9aSAndroid Build Coastguard Worker self.0 621*e1997b9aSAndroid Build Coastguard Worker } 622*e1997b9aSAndroid Build Coastguard Worker } 623*e1997b9aSAndroid Build Coastguard Worker 624*e1997b9aSAndroid Build Coastguard Worker impl Drop for KeyIdGuard { drop(&mut self)625*e1997b9aSAndroid Build Coastguard Worker fn drop(&mut self) { 626*e1997b9aSAndroid Build Coastguard Worker let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap(); 627*e1997b9aSAndroid Build Coastguard Worker locked_keys.remove(&self.0); 628*e1997b9aSAndroid Build Coastguard Worker drop(locked_keys); 629*e1997b9aSAndroid Build Coastguard Worker KEY_ID_LOCK.cond_var.notify_all(); 630*e1997b9aSAndroid Build Coastguard Worker } 631*e1997b9aSAndroid Build Coastguard Worker } 632*e1997b9aSAndroid Build Coastguard Worker 633*e1997b9aSAndroid Build Coastguard Worker /// This type represents a certificate and certificate chain entry for a key. 634*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Default)] 635*e1997b9aSAndroid Build Coastguard Worker pub struct CertificateInfo { 636*e1997b9aSAndroid Build Coastguard Worker cert: Option<Vec<u8>>, 637*e1997b9aSAndroid Build Coastguard Worker cert_chain: Option<Vec<u8>>, 638*e1997b9aSAndroid Build Coastguard Worker } 639*e1997b9aSAndroid Build Coastguard Worker 640*e1997b9aSAndroid Build Coastguard Worker /// This type represents a Blob with its metadata and an optional superseded blob. 641*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug)] 642*e1997b9aSAndroid Build Coastguard Worker pub struct BlobInfo<'a> { 643*e1997b9aSAndroid Build Coastguard Worker blob: &'a [u8], 644*e1997b9aSAndroid Build Coastguard Worker metadata: &'a BlobMetaData, 645*e1997b9aSAndroid Build Coastguard Worker /// Superseded blobs are an artifact of legacy import. In some rare occasions 646*e1997b9aSAndroid Build Coastguard Worker /// the key blob needs to be upgraded during import. In that case two 647*e1997b9aSAndroid Build Coastguard Worker /// blob are imported, the superseded one will have to be imported first, 648*e1997b9aSAndroid Build Coastguard Worker /// so that the garbage collector can reap it. 649*e1997b9aSAndroid Build Coastguard Worker superseded_blob: Option<(&'a [u8], &'a BlobMetaData)>, 650*e1997b9aSAndroid Build Coastguard Worker } 651*e1997b9aSAndroid Build Coastguard Worker 652*e1997b9aSAndroid Build Coastguard Worker impl<'a> BlobInfo<'a> { 653*e1997b9aSAndroid Build Coastguard Worker /// Create a new instance of blob info with blob and corresponding metadata 654*e1997b9aSAndroid Build Coastguard Worker /// and no superseded blob info. new(blob: &'a [u8], metadata: &'a BlobMetaData) -> Self655*e1997b9aSAndroid Build Coastguard Worker pub fn new(blob: &'a [u8], metadata: &'a BlobMetaData) -> Self { 656*e1997b9aSAndroid Build Coastguard Worker Self { blob, metadata, superseded_blob: None } 657*e1997b9aSAndroid Build Coastguard Worker } 658*e1997b9aSAndroid Build Coastguard Worker 659*e1997b9aSAndroid Build Coastguard Worker /// Create a new instance of blob info with blob and corresponding metadata 660*e1997b9aSAndroid Build Coastguard Worker /// as well as superseded blob info. new_with_superseded( blob: &'a [u8], metadata: &'a BlobMetaData, superseded_blob: Option<(&'a [u8], &'a BlobMetaData)>, ) -> Self661*e1997b9aSAndroid Build Coastguard Worker pub fn new_with_superseded( 662*e1997b9aSAndroid Build Coastguard Worker blob: &'a [u8], 663*e1997b9aSAndroid Build Coastguard Worker metadata: &'a BlobMetaData, 664*e1997b9aSAndroid Build Coastguard Worker superseded_blob: Option<(&'a [u8], &'a BlobMetaData)>, 665*e1997b9aSAndroid Build Coastguard Worker ) -> Self { 666*e1997b9aSAndroid Build Coastguard Worker Self { blob, metadata, superseded_blob } 667*e1997b9aSAndroid Build Coastguard Worker } 668*e1997b9aSAndroid Build Coastguard Worker } 669*e1997b9aSAndroid Build Coastguard Worker 670*e1997b9aSAndroid Build Coastguard Worker impl CertificateInfo { 671*e1997b9aSAndroid Build Coastguard Worker /// Constructs a new CertificateInfo object from `cert` and `cert_chain` new(cert: Option<Vec<u8>>, cert_chain: Option<Vec<u8>>) -> Self672*e1997b9aSAndroid Build Coastguard Worker pub fn new(cert: Option<Vec<u8>>, cert_chain: Option<Vec<u8>>) -> Self { 673*e1997b9aSAndroid Build Coastguard Worker Self { cert, cert_chain } 674*e1997b9aSAndroid Build Coastguard Worker } 675*e1997b9aSAndroid Build Coastguard Worker 676*e1997b9aSAndroid Build Coastguard Worker /// Take the cert take_cert(&mut self) -> Option<Vec<u8>>677*e1997b9aSAndroid Build Coastguard Worker pub fn take_cert(&mut self) -> Option<Vec<u8>> { 678*e1997b9aSAndroid Build Coastguard Worker self.cert.take() 679*e1997b9aSAndroid Build Coastguard Worker } 680*e1997b9aSAndroid Build Coastguard Worker 681*e1997b9aSAndroid Build Coastguard Worker /// Take the cert chain take_cert_chain(&mut self) -> Option<Vec<u8>>682*e1997b9aSAndroid Build Coastguard Worker pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> { 683*e1997b9aSAndroid Build Coastguard Worker self.cert_chain.take() 684*e1997b9aSAndroid Build Coastguard Worker } 685*e1997b9aSAndroid Build Coastguard Worker } 686*e1997b9aSAndroid Build Coastguard Worker 687*e1997b9aSAndroid Build Coastguard Worker /// This type represents a certificate chain with a private key corresponding to the leaf 688*e1997b9aSAndroid Build Coastguard Worker /// certificate. TODO(jbires): This will be used in a follow-on CL, for now it's used in the tests. 689*e1997b9aSAndroid Build Coastguard Worker pub struct CertificateChain { 690*e1997b9aSAndroid Build Coastguard Worker /// A KM key blob 691*e1997b9aSAndroid Build Coastguard Worker pub private_key: ZVec, 692*e1997b9aSAndroid Build Coastguard Worker /// A batch cert for private_key 693*e1997b9aSAndroid Build Coastguard Worker pub batch_cert: Vec<u8>, 694*e1997b9aSAndroid Build Coastguard Worker /// A full certificate chain from root signing authority to private_key, including batch_cert 695*e1997b9aSAndroid Build Coastguard Worker /// for convenience. 696*e1997b9aSAndroid Build Coastguard Worker pub cert_chain: Vec<u8>, 697*e1997b9aSAndroid Build Coastguard Worker } 698*e1997b9aSAndroid Build Coastguard Worker 699*e1997b9aSAndroid Build Coastguard Worker /// This type represents a Keystore 2.0 key entry. 700*e1997b9aSAndroid Build Coastguard Worker /// An entry has a unique `id` by which it can be found in the database. 701*e1997b9aSAndroid Build Coastguard Worker /// It has a security level field, key parameters, and three optional fields 702*e1997b9aSAndroid Build Coastguard Worker /// for the KeyMint blob, public certificate and a public certificate chain. 703*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Default, Eq, PartialEq)] 704*e1997b9aSAndroid Build Coastguard Worker pub struct KeyEntry { 705*e1997b9aSAndroid Build Coastguard Worker id: i64, 706*e1997b9aSAndroid Build Coastguard Worker key_blob_info: Option<(Vec<u8>, BlobMetaData)>, 707*e1997b9aSAndroid Build Coastguard Worker cert: Option<Vec<u8>>, 708*e1997b9aSAndroid Build Coastguard Worker cert_chain: Option<Vec<u8>>, 709*e1997b9aSAndroid Build Coastguard Worker km_uuid: Uuid, 710*e1997b9aSAndroid Build Coastguard Worker parameters: Vec<KeyParameter>, 711*e1997b9aSAndroid Build Coastguard Worker metadata: KeyMetaData, 712*e1997b9aSAndroid Build Coastguard Worker pure_cert: bool, 713*e1997b9aSAndroid Build Coastguard Worker } 714*e1997b9aSAndroid Build Coastguard Worker 715*e1997b9aSAndroid Build Coastguard Worker impl KeyEntry { 716*e1997b9aSAndroid Build Coastguard Worker /// Returns the unique id of the Key entry. id(&self) -> i64717*e1997b9aSAndroid Build Coastguard Worker pub fn id(&self) -> i64 { 718*e1997b9aSAndroid Build Coastguard Worker self.id 719*e1997b9aSAndroid Build Coastguard Worker } 720*e1997b9aSAndroid Build Coastguard Worker /// Exposes the optional KeyMint blob. key_blob_info(&self) -> &Option<(Vec<u8>, BlobMetaData)>721*e1997b9aSAndroid Build Coastguard Worker pub fn key_blob_info(&self) -> &Option<(Vec<u8>, BlobMetaData)> { 722*e1997b9aSAndroid Build Coastguard Worker &self.key_blob_info 723*e1997b9aSAndroid Build Coastguard Worker } 724*e1997b9aSAndroid Build Coastguard Worker /// Extracts the Optional KeyMint blob including its metadata. take_key_blob_info(&mut self) -> Option<(Vec<u8>, BlobMetaData)>725*e1997b9aSAndroid Build Coastguard Worker pub fn take_key_blob_info(&mut self) -> Option<(Vec<u8>, BlobMetaData)> { 726*e1997b9aSAndroid Build Coastguard Worker self.key_blob_info.take() 727*e1997b9aSAndroid Build Coastguard Worker } 728*e1997b9aSAndroid Build Coastguard Worker /// Exposes the optional public certificate. cert(&self) -> &Option<Vec<u8>>729*e1997b9aSAndroid Build Coastguard Worker pub fn cert(&self) -> &Option<Vec<u8>> { 730*e1997b9aSAndroid Build Coastguard Worker &self.cert 731*e1997b9aSAndroid Build Coastguard Worker } 732*e1997b9aSAndroid Build Coastguard Worker /// Extracts the optional public certificate. take_cert(&mut self) -> Option<Vec<u8>>733*e1997b9aSAndroid Build Coastguard Worker pub fn take_cert(&mut self) -> Option<Vec<u8>> { 734*e1997b9aSAndroid Build Coastguard Worker self.cert.take() 735*e1997b9aSAndroid Build Coastguard Worker } 736*e1997b9aSAndroid Build Coastguard Worker /// Extracts the optional public certificate_chain. take_cert_chain(&mut self) -> Option<Vec<u8>>737*e1997b9aSAndroid Build Coastguard Worker pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> { 738*e1997b9aSAndroid Build Coastguard Worker self.cert_chain.take() 739*e1997b9aSAndroid Build Coastguard Worker } 740*e1997b9aSAndroid Build Coastguard Worker /// Returns the uuid of the owning KeyMint instance. km_uuid(&self) -> &Uuid741*e1997b9aSAndroid Build Coastguard Worker pub fn km_uuid(&self) -> &Uuid { 742*e1997b9aSAndroid Build Coastguard Worker &self.km_uuid 743*e1997b9aSAndroid Build Coastguard Worker } 744*e1997b9aSAndroid Build Coastguard Worker /// Consumes this key entry and extracts the keyparameters from it. into_key_parameters(self) -> Vec<KeyParameter>745*e1997b9aSAndroid Build Coastguard Worker pub fn into_key_parameters(self) -> Vec<KeyParameter> { 746*e1997b9aSAndroid Build Coastguard Worker self.parameters 747*e1997b9aSAndroid Build Coastguard Worker } 748*e1997b9aSAndroid Build Coastguard Worker /// Exposes the key metadata of this key entry. metadata(&self) -> &KeyMetaData749*e1997b9aSAndroid Build Coastguard Worker pub fn metadata(&self) -> &KeyMetaData { 750*e1997b9aSAndroid Build Coastguard Worker &self.metadata 751*e1997b9aSAndroid Build Coastguard Worker } 752*e1997b9aSAndroid Build Coastguard Worker /// This returns true if the entry is a pure certificate entry with no 753*e1997b9aSAndroid Build Coastguard Worker /// private key component. pure_cert(&self) -> bool754*e1997b9aSAndroid Build Coastguard Worker pub fn pure_cert(&self) -> bool { 755*e1997b9aSAndroid Build Coastguard Worker self.pure_cert 756*e1997b9aSAndroid Build Coastguard Worker } 757*e1997b9aSAndroid Build Coastguard Worker } 758*e1997b9aSAndroid Build Coastguard Worker 759*e1997b9aSAndroid Build Coastguard Worker /// Indicates the sub component of a key entry for persistent storage. 760*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] 761*e1997b9aSAndroid Build Coastguard Worker pub struct SubComponentType(u32); 762*e1997b9aSAndroid Build Coastguard Worker impl SubComponentType { 763*e1997b9aSAndroid Build Coastguard Worker /// Persistent identifier for a key blob. 764*e1997b9aSAndroid Build Coastguard Worker pub const KEY_BLOB: SubComponentType = Self(0); 765*e1997b9aSAndroid Build Coastguard Worker /// Persistent identifier for a certificate blob. 766*e1997b9aSAndroid Build Coastguard Worker pub const CERT: SubComponentType = Self(1); 767*e1997b9aSAndroid Build Coastguard Worker /// Persistent identifier for a certificate chain blob. 768*e1997b9aSAndroid Build Coastguard Worker pub const CERT_CHAIN: SubComponentType = Self(2); 769*e1997b9aSAndroid Build Coastguard Worker } 770*e1997b9aSAndroid Build Coastguard Worker 771*e1997b9aSAndroid Build Coastguard Worker impl ToSql for SubComponentType { to_sql(&self) -> rusqlite::Result<ToSqlOutput>772*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 773*e1997b9aSAndroid Build Coastguard Worker self.0.to_sql() 774*e1997b9aSAndroid Build Coastguard Worker } 775*e1997b9aSAndroid Build Coastguard Worker } 776*e1997b9aSAndroid Build Coastguard Worker 777*e1997b9aSAndroid Build Coastguard Worker impl FromSql for SubComponentType { column_result(value: ValueRef) -> FromSqlResult<Self>778*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 779*e1997b9aSAndroid Build Coastguard Worker Ok(Self(u32::column_result(value)?)) 780*e1997b9aSAndroid Build Coastguard Worker } 781*e1997b9aSAndroid Build Coastguard Worker } 782*e1997b9aSAndroid Build Coastguard Worker 783*e1997b9aSAndroid Build Coastguard Worker /// This trait is private to the database module. It is used to convey whether or not the garbage 784*e1997b9aSAndroid Build Coastguard Worker /// collector shall be invoked after a database access. All closures passed to 785*e1997b9aSAndroid Build Coastguard Worker /// `KeystoreDB::with_transaction` return a tuple (bool, T) where the bool indicates if the 786*e1997b9aSAndroid Build Coastguard Worker /// gc needs to be triggered. This convenience function allows to turn any anyhow::Result<T> 787*e1997b9aSAndroid Build Coastguard Worker /// into anyhow::Result<(bool, T)> by simply appending one of `.do_gc(bool)`, `.no_gc()`, or 788*e1997b9aSAndroid Build Coastguard Worker /// `.need_gc()`. 789*e1997b9aSAndroid Build Coastguard Worker trait DoGc<T> { do_gc(self, need_gc: bool) -> Result<(bool, T)>790*e1997b9aSAndroid Build Coastguard Worker fn do_gc(self, need_gc: bool) -> Result<(bool, T)>; 791*e1997b9aSAndroid Build Coastguard Worker no_gc(self) -> Result<(bool, T)>792*e1997b9aSAndroid Build Coastguard Worker fn no_gc(self) -> Result<(bool, T)>; 793*e1997b9aSAndroid Build Coastguard Worker need_gc(self) -> Result<(bool, T)>794*e1997b9aSAndroid Build Coastguard Worker fn need_gc(self) -> Result<(bool, T)>; 795*e1997b9aSAndroid Build Coastguard Worker } 796*e1997b9aSAndroid Build Coastguard Worker 797*e1997b9aSAndroid Build Coastguard Worker impl<T> DoGc<T> for Result<T> { do_gc(self, need_gc: bool) -> Result<(bool, T)>798*e1997b9aSAndroid Build Coastguard Worker fn do_gc(self, need_gc: bool) -> Result<(bool, T)> { 799*e1997b9aSAndroid Build Coastguard Worker self.map(|r| (need_gc, r)) 800*e1997b9aSAndroid Build Coastguard Worker } 801*e1997b9aSAndroid Build Coastguard Worker no_gc(self) -> Result<(bool, T)>802*e1997b9aSAndroid Build Coastguard Worker fn no_gc(self) -> Result<(bool, T)> { 803*e1997b9aSAndroid Build Coastguard Worker self.do_gc(false) 804*e1997b9aSAndroid Build Coastguard Worker } 805*e1997b9aSAndroid Build Coastguard Worker need_gc(self) -> Result<(bool, T)>806*e1997b9aSAndroid Build Coastguard Worker fn need_gc(self) -> Result<(bool, T)> { 807*e1997b9aSAndroid Build Coastguard Worker self.do_gc(true) 808*e1997b9aSAndroid Build Coastguard Worker } 809*e1997b9aSAndroid Build Coastguard Worker } 810*e1997b9aSAndroid Build Coastguard Worker 811*e1997b9aSAndroid Build Coastguard Worker /// KeystoreDB wraps a connection to an SQLite database and tracks its 812*e1997b9aSAndroid Build Coastguard Worker /// ownership. It also implements all of Keystore 2.0's database functionality. 813*e1997b9aSAndroid Build Coastguard Worker pub struct KeystoreDB { 814*e1997b9aSAndroid Build Coastguard Worker conn: Connection, 815*e1997b9aSAndroid Build Coastguard Worker gc: Option<Arc<Gc>>, 816*e1997b9aSAndroid Build Coastguard Worker perboot: Arc<perboot::PerbootDB>, 817*e1997b9aSAndroid Build Coastguard Worker } 818*e1997b9aSAndroid Build Coastguard Worker 819*e1997b9aSAndroid Build Coastguard Worker /// Database representation of the monotonic time retrieved from the system call clock_gettime with 820*e1997b9aSAndroid Build Coastguard Worker /// CLOCK_BOOTTIME. Stores monotonic time as i64 in milliseconds. 821*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)] 822*e1997b9aSAndroid Build Coastguard Worker pub struct BootTime(i64); 823*e1997b9aSAndroid Build Coastguard Worker 824*e1997b9aSAndroid Build Coastguard Worker impl BootTime { 825*e1997b9aSAndroid Build Coastguard Worker /// Constructs a new BootTime now() -> Self826*e1997b9aSAndroid Build Coastguard Worker pub fn now() -> Self { 827*e1997b9aSAndroid Build Coastguard Worker Self(get_current_time_in_milliseconds()) 828*e1997b9aSAndroid Build Coastguard Worker } 829*e1997b9aSAndroid Build Coastguard Worker 830*e1997b9aSAndroid Build Coastguard Worker /// Returns the value of BootTime in milliseconds as i64 milliseconds(&self) -> i64831*e1997b9aSAndroid Build Coastguard Worker pub fn milliseconds(&self) -> i64 { 832*e1997b9aSAndroid Build Coastguard Worker self.0 833*e1997b9aSAndroid Build Coastguard Worker } 834*e1997b9aSAndroid Build Coastguard Worker 835*e1997b9aSAndroid Build Coastguard Worker /// Returns the integer value of BootTime as i64 seconds(&self) -> i64836*e1997b9aSAndroid Build Coastguard Worker pub fn seconds(&self) -> i64 { 837*e1997b9aSAndroid Build Coastguard Worker self.0 / 1000 838*e1997b9aSAndroid Build Coastguard Worker } 839*e1997b9aSAndroid Build Coastguard Worker 840*e1997b9aSAndroid Build Coastguard Worker /// Like i64::checked_sub. checked_sub(&self, other: &Self) -> Option<Self>841*e1997b9aSAndroid Build Coastguard Worker pub fn checked_sub(&self, other: &Self) -> Option<Self> { 842*e1997b9aSAndroid Build Coastguard Worker self.0.checked_sub(other.0).map(Self) 843*e1997b9aSAndroid Build Coastguard Worker } 844*e1997b9aSAndroid Build Coastguard Worker } 845*e1997b9aSAndroid Build Coastguard Worker 846*e1997b9aSAndroid Build Coastguard Worker impl ToSql for BootTime { to_sql(&self) -> rusqlite::Result<ToSqlOutput>847*e1997b9aSAndroid Build Coastguard Worker fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> { 848*e1997b9aSAndroid Build Coastguard Worker Ok(ToSqlOutput::Owned(Value::Integer(self.0))) 849*e1997b9aSAndroid Build Coastguard Worker } 850*e1997b9aSAndroid Build Coastguard Worker } 851*e1997b9aSAndroid Build Coastguard Worker 852*e1997b9aSAndroid Build Coastguard Worker impl FromSql for BootTime { column_result(value: ValueRef) -> FromSqlResult<Self>853*e1997b9aSAndroid Build Coastguard Worker fn column_result(value: ValueRef) -> FromSqlResult<Self> { 854*e1997b9aSAndroid Build Coastguard Worker Ok(Self(i64::column_result(value)?)) 855*e1997b9aSAndroid Build Coastguard Worker } 856*e1997b9aSAndroid Build Coastguard Worker } 857*e1997b9aSAndroid Build Coastguard Worker 858*e1997b9aSAndroid Build Coastguard Worker /// This struct encapsulates the information to be stored in the database about the auth tokens 859*e1997b9aSAndroid Build Coastguard Worker /// received by keystore. 860*e1997b9aSAndroid Build Coastguard Worker #[derive(Clone)] 861*e1997b9aSAndroid Build Coastguard Worker pub struct AuthTokenEntry { 862*e1997b9aSAndroid Build Coastguard Worker auth_token: HardwareAuthToken, 863*e1997b9aSAndroid Build Coastguard Worker // Time received in milliseconds 864*e1997b9aSAndroid Build Coastguard Worker time_received: BootTime, 865*e1997b9aSAndroid Build Coastguard Worker } 866*e1997b9aSAndroid Build Coastguard Worker 867*e1997b9aSAndroid Build Coastguard Worker impl AuthTokenEntry { new(auth_token: HardwareAuthToken, time_received: BootTime) -> Self868*e1997b9aSAndroid Build Coastguard Worker fn new(auth_token: HardwareAuthToken, time_received: BootTime) -> Self { 869*e1997b9aSAndroid Build Coastguard Worker AuthTokenEntry { auth_token, time_received } 870*e1997b9aSAndroid Build Coastguard Worker } 871*e1997b9aSAndroid Build Coastguard Worker 872*e1997b9aSAndroid Build Coastguard Worker /// Checks if this auth token satisfies the given authentication information. satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool873*e1997b9aSAndroid Build Coastguard Worker pub fn satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool { 874*e1997b9aSAndroid Build Coastguard Worker user_secure_ids.iter().any(|&sid| { 875*e1997b9aSAndroid Build Coastguard Worker (sid == self.auth_token.userId || sid == self.auth_token.authenticatorId) 876*e1997b9aSAndroid Build Coastguard Worker && ((auth_type.0 & self.auth_token.authenticatorType.0) != 0) 877*e1997b9aSAndroid Build Coastguard Worker }) 878*e1997b9aSAndroid Build Coastguard Worker } 879*e1997b9aSAndroid Build Coastguard Worker 880*e1997b9aSAndroid Build Coastguard Worker /// Returns the auth token wrapped by the AuthTokenEntry auth_token(&self) -> &HardwareAuthToken881*e1997b9aSAndroid Build Coastguard Worker pub fn auth_token(&self) -> &HardwareAuthToken { 882*e1997b9aSAndroid Build Coastguard Worker &self.auth_token 883*e1997b9aSAndroid Build Coastguard Worker } 884*e1997b9aSAndroid Build Coastguard Worker 885*e1997b9aSAndroid Build Coastguard Worker /// Returns the auth token wrapped by the AuthTokenEntry take_auth_token(self) -> HardwareAuthToken886*e1997b9aSAndroid Build Coastguard Worker pub fn take_auth_token(self) -> HardwareAuthToken { 887*e1997b9aSAndroid Build Coastguard Worker self.auth_token 888*e1997b9aSAndroid Build Coastguard Worker } 889*e1997b9aSAndroid Build Coastguard Worker 890*e1997b9aSAndroid Build Coastguard Worker /// Returns the time that this auth token was received. time_received(&self) -> BootTime891*e1997b9aSAndroid Build Coastguard Worker pub fn time_received(&self) -> BootTime { 892*e1997b9aSAndroid Build Coastguard Worker self.time_received 893*e1997b9aSAndroid Build Coastguard Worker } 894*e1997b9aSAndroid Build Coastguard Worker 895*e1997b9aSAndroid Build Coastguard Worker /// Returns the challenge value of the auth token. challenge(&self) -> i64896*e1997b9aSAndroid Build Coastguard Worker pub fn challenge(&self) -> i64 { 897*e1997b9aSAndroid Build Coastguard Worker self.auth_token.challenge 898*e1997b9aSAndroid Build Coastguard Worker } 899*e1997b9aSAndroid Build Coastguard Worker } 900*e1997b9aSAndroid Build Coastguard Worker 901*e1997b9aSAndroid Build Coastguard Worker /// Information about a superseded blob (a blob that is no longer the 902*e1997b9aSAndroid Build Coastguard Worker /// most recent blob of that type for a given key, due to upgrade or 903*e1997b9aSAndroid Build Coastguard Worker /// replacement). 904*e1997b9aSAndroid Build Coastguard Worker pub struct SupersededBlob { 905*e1997b9aSAndroid Build Coastguard Worker /// ID 906*e1997b9aSAndroid Build Coastguard Worker pub blob_id: i64, 907*e1997b9aSAndroid Build Coastguard Worker /// Contents. 908*e1997b9aSAndroid Build Coastguard Worker pub blob: Vec<u8>, 909*e1997b9aSAndroid Build Coastguard Worker /// Metadata. 910*e1997b9aSAndroid Build Coastguard Worker pub metadata: BlobMetaData, 911*e1997b9aSAndroid Build Coastguard Worker } 912*e1997b9aSAndroid Build Coastguard Worker 913*e1997b9aSAndroid Build Coastguard Worker impl KeystoreDB { 914*e1997b9aSAndroid Build Coastguard Worker const UNASSIGNED_KEY_ID: i64 = -1i64; 915*e1997b9aSAndroid Build Coastguard Worker const CURRENT_DB_VERSION: u32 = 2; 916*e1997b9aSAndroid Build Coastguard Worker const UPGRADERS: &'static [fn(&Transaction) -> Result<u32>] = 917*e1997b9aSAndroid Build Coastguard Worker &[Self::from_0_to_1, Self::from_1_to_2]; 918*e1997b9aSAndroid Build Coastguard Worker 919*e1997b9aSAndroid Build Coastguard Worker /// Name of the file that holds the cross-boot persistent database. 920*e1997b9aSAndroid Build Coastguard Worker pub const PERSISTENT_DB_FILENAME: &'static str = "persistent.sqlite"; 921*e1997b9aSAndroid Build Coastguard Worker 922*e1997b9aSAndroid Build Coastguard Worker /// This will create a new database connection connecting the two 923*e1997b9aSAndroid Build Coastguard Worker /// files persistent.sqlite and perboot.sqlite in the given directory. 924*e1997b9aSAndroid Build Coastguard Worker /// It also attempts to initialize all of the tables. 925*e1997b9aSAndroid Build Coastguard Worker /// KeystoreDB cannot be used by multiple threads. 926*e1997b9aSAndroid Build Coastguard Worker /// Each thread should open their own connection using `thread_local!`. new(db_root: &Path, gc: Option<Arc<Gc>>) -> Result<Self>927*e1997b9aSAndroid Build Coastguard Worker pub fn new(db_root: &Path, gc: Option<Arc<Gc>>) -> Result<Self> { 928*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::new"); 929*e1997b9aSAndroid Build Coastguard Worker 930*e1997b9aSAndroid Build Coastguard Worker let persistent_path = Self::make_persistent_path(db_root)?; 931*e1997b9aSAndroid Build Coastguard Worker let conn = Self::make_connection(&persistent_path)?; 932*e1997b9aSAndroid Build Coastguard Worker 933*e1997b9aSAndroid Build Coastguard Worker let mut db = Self { conn, gc, perboot: perboot::PERBOOT_DB.clone() }; 934*e1997b9aSAndroid Build Coastguard Worker db.with_transaction(Immediate("TX_new"), |tx| { 935*e1997b9aSAndroid Build Coastguard Worker versioning::upgrade_database(tx, Self::CURRENT_DB_VERSION, Self::UPGRADERS) 936*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("KeystoreDB::new: trying to upgrade database."))?; 937*e1997b9aSAndroid Build Coastguard Worker Self::init_tables(tx).context("Trying to initialize tables.").no_gc() 938*e1997b9aSAndroid Build Coastguard Worker })?; 939*e1997b9aSAndroid Build Coastguard Worker Ok(db) 940*e1997b9aSAndroid Build Coastguard Worker } 941*e1997b9aSAndroid Build Coastguard Worker 942*e1997b9aSAndroid Build Coastguard Worker // This upgrade function deletes all MAX_BOOT_LEVEL keys, that were generated before 943*e1997b9aSAndroid Build Coastguard Worker // cryptographic binding to the boot level keys was implemented. from_0_to_1(tx: &Transaction) -> Result<u32>944*e1997b9aSAndroid Build Coastguard Worker fn from_0_to_1(tx: &Transaction) -> Result<u32> { 945*e1997b9aSAndroid Build Coastguard Worker tx.execute( 946*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.keyentry SET state = ? 947*e1997b9aSAndroid Build Coastguard Worker WHERE 948*e1997b9aSAndroid Build Coastguard Worker id IN (SELECT keyentryid FROM persistent.keyparameter WHERE tag = ?) 949*e1997b9aSAndroid Build Coastguard Worker AND 950*e1997b9aSAndroid Build Coastguard Worker id NOT IN ( 951*e1997b9aSAndroid Build Coastguard Worker SELECT keyentryid FROM persistent.blobentry 952*e1997b9aSAndroid Build Coastguard Worker WHERE id IN ( 953*e1997b9aSAndroid Build Coastguard Worker SELECT blobentryid FROM persistent.blobmetadata WHERE tag = ? 954*e1997b9aSAndroid Build Coastguard Worker ) 955*e1997b9aSAndroid Build Coastguard Worker );", 956*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced, Tag::MAX_BOOT_LEVEL.0, BlobMetaData::MaxBootLevel], 957*e1997b9aSAndroid Build Coastguard Worker ) 958*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to delete logical boot level keys."))?; 959*e1997b9aSAndroid Build Coastguard Worker 960*e1997b9aSAndroid Build Coastguard Worker // DB version is now 1. 961*e1997b9aSAndroid Build Coastguard Worker Ok(1) 962*e1997b9aSAndroid Build Coastguard Worker } 963*e1997b9aSAndroid Build Coastguard Worker 964*e1997b9aSAndroid Build Coastguard Worker // This upgrade function adds an additional `state INTEGER` column to the blobentry 965*e1997b9aSAndroid Build Coastguard Worker // table, and populates it based on whether each blob is the most recent of its type for 966*e1997b9aSAndroid Build Coastguard Worker // the corresponding key. from_1_to_2(tx: &Transaction) -> Result<u32>967*e1997b9aSAndroid Build Coastguard Worker fn from_1_to_2(tx: &Transaction) -> Result<u32> { 968*e1997b9aSAndroid Build Coastguard Worker tx.execute( 969*e1997b9aSAndroid Build Coastguard Worker "ALTER TABLE persistent.blobentry ADD COLUMN state INTEGER DEFAULT 0;", 970*e1997b9aSAndroid Build Coastguard Worker params![], 971*e1997b9aSAndroid Build Coastguard Worker ) 972*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to add state column"))?; 973*e1997b9aSAndroid Build Coastguard Worker 974*e1997b9aSAndroid Build Coastguard Worker // Mark keyblobs that are not the most recent for their corresponding key. 975*e1997b9aSAndroid Build Coastguard Worker // This may take a while if there are excessive numbers of keys in the database. 976*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::from_1_to_2 mark all non-current keyblobs"); 977*e1997b9aSAndroid Build Coastguard Worker let sc_key_blob = SubComponentType::KEY_BLOB; 978*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 979*e1997b9aSAndroid Build Coastguard Worker .prepare( 980*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.blobentry SET state=? 981*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? 982*e1997b9aSAndroid Build Coastguard Worker AND id NOT IN ( 983*e1997b9aSAndroid Build Coastguard Worker SELECT MAX(id) FROM persistent.blobentry 984*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? 985*e1997b9aSAndroid Build Coastguard Worker GROUP BY keyentryid, subcomponent_type 986*e1997b9aSAndroid Build Coastguard Worker );", 987*e1997b9aSAndroid Build Coastguard Worker ) 988*e1997b9aSAndroid Build Coastguard Worker .context("Trying to prepare query to mark superseded keyblobs")?; 989*e1997b9aSAndroid Build Coastguard Worker stmt.execute(params![BlobState::Superseded, sc_key_blob, sc_key_blob]) 990*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to set state=superseded state for keyblobs"))?; 991*e1997b9aSAndroid Build Coastguard Worker log::info!("marked non-current blobentry rows for keyblobs as superseded"); 992*e1997b9aSAndroid Build Coastguard Worker 993*e1997b9aSAndroid Build Coastguard Worker // Mark keyblobs that don't have a corresponding key. 994*e1997b9aSAndroid Build Coastguard Worker // This may take a while if there are excessive numbers of keys in the database. 995*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::from_1_to_2 mark all orphaned keyblobs"); 996*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 997*e1997b9aSAndroid Build Coastguard Worker .prepare( 998*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.blobentry SET state=? 999*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? 1000*e1997b9aSAndroid Build Coastguard Worker AND NOT EXISTS (SELECT id FROM persistent.keyentry 1001*e1997b9aSAndroid Build Coastguard Worker WHERE id = keyentryid);", 1002*e1997b9aSAndroid Build Coastguard Worker ) 1003*e1997b9aSAndroid Build Coastguard Worker .context("Trying to prepare query to mark orphaned keyblobs")?; 1004*e1997b9aSAndroid Build Coastguard Worker stmt.execute(params![BlobState::Orphaned, sc_key_blob]) 1005*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to set state=orphaned for keyblobs"))?; 1006*e1997b9aSAndroid Build Coastguard Worker log::info!("marked orphaned blobentry rows for keyblobs"); 1007*e1997b9aSAndroid Build Coastguard Worker 1008*e1997b9aSAndroid Build Coastguard Worker // Add an index to make it fast to find out of date blobentry rows. 1009*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::from_1_to_2 add blobentry index"); 1010*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1011*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.blobentry_state_index 1012*e1997b9aSAndroid Build Coastguard Worker ON blobentry(subcomponent_type, state);", 1013*e1997b9aSAndroid Build Coastguard Worker [], 1014*e1997b9aSAndroid Build Coastguard Worker ) 1015*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index blobentry_state_index.")?; 1016*e1997b9aSAndroid Build Coastguard Worker 1017*e1997b9aSAndroid Build Coastguard Worker // Add an index to make it fast to find unreferenced keyentry rows. 1018*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::from_1_to_2 add keyentry state index"); 1019*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1020*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.keyentry_state_index 1021*e1997b9aSAndroid Build Coastguard Worker ON keyentry(state);", 1022*e1997b9aSAndroid Build Coastguard Worker [], 1023*e1997b9aSAndroid Build Coastguard Worker ) 1024*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index keyentry_state_index.")?; 1025*e1997b9aSAndroid Build Coastguard Worker 1026*e1997b9aSAndroid Build Coastguard Worker // DB version is now 2. 1027*e1997b9aSAndroid Build Coastguard Worker Ok(2) 1028*e1997b9aSAndroid Build Coastguard Worker } 1029*e1997b9aSAndroid Build Coastguard Worker init_tables(tx: &Transaction) -> Result<()>1030*e1997b9aSAndroid Build Coastguard Worker fn init_tables(tx: &Transaction) -> Result<()> { 1031*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1032*e1997b9aSAndroid Build Coastguard Worker "CREATE TABLE IF NOT EXISTS persistent.keyentry ( 1033*e1997b9aSAndroid Build Coastguard Worker id INTEGER UNIQUE, 1034*e1997b9aSAndroid Build Coastguard Worker key_type INTEGER, 1035*e1997b9aSAndroid Build Coastguard Worker domain INTEGER, 1036*e1997b9aSAndroid Build Coastguard Worker namespace INTEGER, 1037*e1997b9aSAndroid Build Coastguard Worker alias BLOB, 1038*e1997b9aSAndroid Build Coastguard Worker state INTEGER, 1039*e1997b9aSAndroid Build Coastguard Worker km_uuid BLOB);", 1040*e1997b9aSAndroid Build Coastguard Worker [], 1041*e1997b9aSAndroid Build Coastguard Worker ) 1042*e1997b9aSAndroid Build Coastguard Worker .context("Failed to initialize \"keyentry\" table.")?; 1043*e1997b9aSAndroid Build Coastguard Worker 1044*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1045*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.keyentry_id_index 1046*e1997b9aSAndroid Build Coastguard Worker ON keyentry(id);", 1047*e1997b9aSAndroid Build Coastguard Worker [], 1048*e1997b9aSAndroid Build Coastguard Worker ) 1049*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index keyentry_id_index.")?; 1050*e1997b9aSAndroid Build Coastguard Worker 1051*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1052*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.keyentry_domain_namespace_index 1053*e1997b9aSAndroid Build Coastguard Worker ON keyentry(domain, namespace, alias);", 1054*e1997b9aSAndroid Build Coastguard Worker [], 1055*e1997b9aSAndroid Build Coastguard Worker ) 1056*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index keyentry_domain_namespace_index.")?; 1057*e1997b9aSAndroid Build Coastguard Worker 1058*e1997b9aSAndroid Build Coastguard Worker // Index added in v2 of database schema. 1059*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1060*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.keyentry_state_index 1061*e1997b9aSAndroid Build Coastguard Worker ON keyentry(state);", 1062*e1997b9aSAndroid Build Coastguard Worker [], 1063*e1997b9aSAndroid Build Coastguard Worker ) 1064*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index keyentry_state_index.")?; 1065*e1997b9aSAndroid Build Coastguard Worker 1066*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1067*e1997b9aSAndroid Build Coastguard Worker "CREATE TABLE IF NOT EXISTS persistent.blobentry ( 1068*e1997b9aSAndroid Build Coastguard Worker id INTEGER PRIMARY KEY, 1069*e1997b9aSAndroid Build Coastguard Worker subcomponent_type INTEGER, 1070*e1997b9aSAndroid Build Coastguard Worker keyentryid INTEGER, 1071*e1997b9aSAndroid Build Coastguard Worker blob BLOB, 1072*e1997b9aSAndroid Build Coastguard Worker state INTEGER DEFAULT 0);", // `state` added in v2 of schema 1073*e1997b9aSAndroid Build Coastguard Worker [], 1074*e1997b9aSAndroid Build Coastguard Worker ) 1075*e1997b9aSAndroid Build Coastguard Worker .context("Failed to initialize \"blobentry\" table.")?; 1076*e1997b9aSAndroid Build Coastguard Worker 1077*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1078*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.blobentry_keyentryid_index 1079*e1997b9aSAndroid Build Coastguard Worker ON blobentry(keyentryid);", 1080*e1997b9aSAndroid Build Coastguard Worker [], 1081*e1997b9aSAndroid Build Coastguard Worker ) 1082*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index blobentry_keyentryid_index.")?; 1083*e1997b9aSAndroid Build Coastguard Worker 1084*e1997b9aSAndroid Build Coastguard Worker // Index added in v2 of database schema. 1085*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1086*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.blobentry_state_index 1087*e1997b9aSAndroid Build Coastguard Worker ON blobentry(subcomponent_type, state);", 1088*e1997b9aSAndroid Build Coastguard Worker [], 1089*e1997b9aSAndroid Build Coastguard Worker ) 1090*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index blobentry_state_index.")?; 1091*e1997b9aSAndroid Build Coastguard Worker 1092*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1093*e1997b9aSAndroid Build Coastguard Worker "CREATE TABLE IF NOT EXISTS persistent.blobmetadata ( 1094*e1997b9aSAndroid Build Coastguard Worker id INTEGER PRIMARY KEY, 1095*e1997b9aSAndroid Build Coastguard Worker blobentryid INTEGER, 1096*e1997b9aSAndroid Build Coastguard Worker tag INTEGER, 1097*e1997b9aSAndroid Build Coastguard Worker data ANY, 1098*e1997b9aSAndroid Build Coastguard Worker UNIQUE (blobentryid, tag));", 1099*e1997b9aSAndroid Build Coastguard Worker [], 1100*e1997b9aSAndroid Build Coastguard Worker ) 1101*e1997b9aSAndroid Build Coastguard Worker .context("Failed to initialize \"blobmetadata\" table.")?; 1102*e1997b9aSAndroid Build Coastguard Worker 1103*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1104*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.blobmetadata_blobentryid_index 1105*e1997b9aSAndroid Build Coastguard Worker ON blobmetadata(blobentryid);", 1106*e1997b9aSAndroid Build Coastguard Worker [], 1107*e1997b9aSAndroid Build Coastguard Worker ) 1108*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index blobmetadata_blobentryid_index.")?; 1109*e1997b9aSAndroid Build Coastguard Worker 1110*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1111*e1997b9aSAndroid Build Coastguard Worker "CREATE TABLE IF NOT EXISTS persistent.keyparameter ( 1112*e1997b9aSAndroid Build Coastguard Worker keyentryid INTEGER, 1113*e1997b9aSAndroid Build Coastguard Worker tag INTEGER, 1114*e1997b9aSAndroid Build Coastguard Worker data ANY, 1115*e1997b9aSAndroid Build Coastguard Worker security_level INTEGER);", 1116*e1997b9aSAndroid Build Coastguard Worker [], 1117*e1997b9aSAndroid Build Coastguard Worker ) 1118*e1997b9aSAndroid Build Coastguard Worker .context("Failed to initialize \"keyparameter\" table.")?; 1119*e1997b9aSAndroid Build Coastguard Worker 1120*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1121*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.keyparameter_keyentryid_index 1122*e1997b9aSAndroid Build Coastguard Worker ON keyparameter(keyentryid);", 1123*e1997b9aSAndroid Build Coastguard Worker [], 1124*e1997b9aSAndroid Build Coastguard Worker ) 1125*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index keyparameter_keyentryid_index.")?; 1126*e1997b9aSAndroid Build Coastguard Worker 1127*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1128*e1997b9aSAndroid Build Coastguard Worker "CREATE TABLE IF NOT EXISTS persistent.keymetadata ( 1129*e1997b9aSAndroid Build Coastguard Worker keyentryid INTEGER, 1130*e1997b9aSAndroid Build Coastguard Worker tag INTEGER, 1131*e1997b9aSAndroid Build Coastguard Worker data ANY, 1132*e1997b9aSAndroid Build Coastguard Worker UNIQUE (keyentryid, tag));", 1133*e1997b9aSAndroid Build Coastguard Worker [], 1134*e1997b9aSAndroid Build Coastguard Worker ) 1135*e1997b9aSAndroid Build Coastguard Worker .context("Failed to initialize \"keymetadata\" table.")?; 1136*e1997b9aSAndroid Build Coastguard Worker 1137*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1138*e1997b9aSAndroid Build Coastguard Worker "CREATE INDEX IF NOT EXISTS persistent.keymetadata_keyentryid_index 1139*e1997b9aSAndroid Build Coastguard Worker ON keymetadata(keyentryid);", 1140*e1997b9aSAndroid Build Coastguard Worker [], 1141*e1997b9aSAndroid Build Coastguard Worker ) 1142*e1997b9aSAndroid Build Coastguard Worker .context("Failed to create index keymetadata_keyentryid_index.")?; 1143*e1997b9aSAndroid Build Coastguard Worker 1144*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1145*e1997b9aSAndroid Build Coastguard Worker "CREATE TABLE IF NOT EXISTS persistent.grant ( 1146*e1997b9aSAndroid Build Coastguard Worker id INTEGER UNIQUE, 1147*e1997b9aSAndroid Build Coastguard Worker grantee INTEGER, 1148*e1997b9aSAndroid Build Coastguard Worker keyentryid INTEGER, 1149*e1997b9aSAndroid Build Coastguard Worker access_vector INTEGER);", 1150*e1997b9aSAndroid Build Coastguard Worker [], 1151*e1997b9aSAndroid Build Coastguard Worker ) 1152*e1997b9aSAndroid Build Coastguard Worker .context("Failed to initialize \"grant\" table.")?; 1153*e1997b9aSAndroid Build Coastguard Worker 1154*e1997b9aSAndroid Build Coastguard Worker Ok(()) 1155*e1997b9aSAndroid Build Coastguard Worker } 1156*e1997b9aSAndroid Build Coastguard Worker make_persistent_path(db_root: &Path) -> Result<String>1157*e1997b9aSAndroid Build Coastguard Worker fn make_persistent_path(db_root: &Path) -> Result<String> { 1158*e1997b9aSAndroid Build Coastguard Worker // Build the path to the sqlite file. 1159*e1997b9aSAndroid Build Coastguard Worker let mut persistent_path = db_root.to_path_buf(); 1160*e1997b9aSAndroid Build Coastguard Worker persistent_path.push(Self::PERSISTENT_DB_FILENAME); 1161*e1997b9aSAndroid Build Coastguard Worker 1162*e1997b9aSAndroid Build Coastguard Worker // Now convert them to strings prefixed with "file:" 1163*e1997b9aSAndroid Build Coastguard Worker let mut persistent_path_str = "file:".to_owned(); 1164*e1997b9aSAndroid Build Coastguard Worker persistent_path_str.push_str(&persistent_path.to_string_lossy()); 1165*e1997b9aSAndroid Build Coastguard Worker 1166*e1997b9aSAndroid Build Coastguard Worker // Connect to database in specific mode 1167*e1997b9aSAndroid Build Coastguard Worker let persistent_path_mode = if keystore2_flags::wal_db_journalmode_v3() { 1168*e1997b9aSAndroid Build Coastguard Worker "?journal_mode=WAL".to_owned() 1169*e1997b9aSAndroid Build Coastguard Worker } else { 1170*e1997b9aSAndroid Build Coastguard Worker "?journal_mode=DELETE".to_owned() 1171*e1997b9aSAndroid Build Coastguard Worker }; 1172*e1997b9aSAndroid Build Coastguard Worker persistent_path_str.push_str(&persistent_path_mode); 1173*e1997b9aSAndroid Build Coastguard Worker 1174*e1997b9aSAndroid Build Coastguard Worker Ok(persistent_path_str) 1175*e1997b9aSAndroid Build Coastguard Worker } 1176*e1997b9aSAndroid Build Coastguard Worker make_connection(persistent_file: &str) -> Result<Connection>1177*e1997b9aSAndroid Build Coastguard Worker fn make_connection(persistent_file: &str) -> Result<Connection> { 1178*e1997b9aSAndroid Build Coastguard Worker let conn = 1179*e1997b9aSAndroid Build Coastguard Worker Connection::open_in_memory().context("Failed to initialize SQLite connection.")?; 1180*e1997b9aSAndroid Build Coastguard Worker 1181*e1997b9aSAndroid Build Coastguard Worker loop { 1182*e1997b9aSAndroid Build Coastguard Worker if let Err(e) = conn 1183*e1997b9aSAndroid Build Coastguard Worker .execute("ATTACH DATABASE ? as persistent;", params![persistent_file]) 1184*e1997b9aSAndroid Build Coastguard Worker .context("Failed to attach database persistent.") 1185*e1997b9aSAndroid Build Coastguard Worker { 1186*e1997b9aSAndroid Build Coastguard Worker if Self::is_locked_error(&e) { 1187*e1997b9aSAndroid Build Coastguard Worker std::thread::sleep(DB_BUSY_RETRY_INTERVAL); 1188*e1997b9aSAndroid Build Coastguard Worker continue; 1189*e1997b9aSAndroid Build Coastguard Worker } else { 1190*e1997b9aSAndroid Build Coastguard Worker return Err(e); 1191*e1997b9aSAndroid Build Coastguard Worker } 1192*e1997b9aSAndroid Build Coastguard Worker } 1193*e1997b9aSAndroid Build Coastguard Worker break; 1194*e1997b9aSAndroid Build Coastguard Worker } 1195*e1997b9aSAndroid Build Coastguard Worker 1196*e1997b9aSAndroid Build Coastguard Worker // Drop the cache size from default (2M) to 0.5M 1197*e1997b9aSAndroid Build Coastguard Worker conn.execute("PRAGMA persistent.cache_size = -500;", params![]) 1198*e1997b9aSAndroid Build Coastguard Worker .context("Failed to decrease cache size for persistent db")?; 1199*e1997b9aSAndroid Build Coastguard Worker 1200*e1997b9aSAndroid Build Coastguard Worker Ok(conn) 1201*e1997b9aSAndroid Build Coastguard Worker } 1202*e1997b9aSAndroid Build Coastguard Worker do_table_size_query( &mut self, storage_type: MetricsStorage, query: &str, params: &[&str], ) -> Result<StorageStats>1203*e1997b9aSAndroid Build Coastguard Worker fn do_table_size_query( 1204*e1997b9aSAndroid Build Coastguard Worker &mut self, 1205*e1997b9aSAndroid Build Coastguard Worker storage_type: MetricsStorage, 1206*e1997b9aSAndroid Build Coastguard Worker query: &str, 1207*e1997b9aSAndroid Build Coastguard Worker params: &[&str], 1208*e1997b9aSAndroid Build Coastguard Worker ) -> Result<StorageStats> { 1209*e1997b9aSAndroid Build Coastguard Worker let (total, unused) = self.with_transaction(TransactionBehavior::Deferred, |tx| { 1210*e1997b9aSAndroid Build Coastguard Worker tx.query_row(query, params_from_iter(params), |row| Ok((row.get(0)?, row.get(1)?))) 1211*e1997b9aSAndroid Build Coastguard Worker .with_context(|| { 1212*e1997b9aSAndroid Build Coastguard Worker ks_err!("get_storage_stat: Error size of storage type {}", storage_type.0) 1213*e1997b9aSAndroid Build Coastguard Worker }) 1214*e1997b9aSAndroid Build Coastguard Worker .no_gc() 1215*e1997b9aSAndroid Build Coastguard Worker })?; 1216*e1997b9aSAndroid Build Coastguard Worker Ok(StorageStats { storage_type, size: total, unused_size: unused }) 1217*e1997b9aSAndroid Build Coastguard Worker } 1218*e1997b9aSAndroid Build Coastguard Worker get_total_size(&mut self) -> Result<StorageStats>1219*e1997b9aSAndroid Build Coastguard Worker fn get_total_size(&mut self) -> Result<StorageStats> { 1220*e1997b9aSAndroid Build Coastguard Worker self.do_table_size_query( 1221*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::DATABASE, 1222*e1997b9aSAndroid Build Coastguard Worker "SELECT page_count * page_size, freelist_count * page_size 1223*e1997b9aSAndroid Build Coastguard Worker FROM pragma_page_count('persistent'), 1224*e1997b9aSAndroid Build Coastguard Worker pragma_page_size('persistent'), 1225*e1997b9aSAndroid Build Coastguard Worker persistent.pragma_freelist_count();", 1226*e1997b9aSAndroid Build Coastguard Worker &[], 1227*e1997b9aSAndroid Build Coastguard Worker ) 1228*e1997b9aSAndroid Build Coastguard Worker } 1229*e1997b9aSAndroid Build Coastguard Worker get_table_size( &mut self, storage_type: MetricsStorage, schema: &str, table: &str, ) -> Result<StorageStats>1230*e1997b9aSAndroid Build Coastguard Worker fn get_table_size( 1231*e1997b9aSAndroid Build Coastguard Worker &mut self, 1232*e1997b9aSAndroid Build Coastguard Worker storage_type: MetricsStorage, 1233*e1997b9aSAndroid Build Coastguard Worker schema: &str, 1234*e1997b9aSAndroid Build Coastguard Worker table: &str, 1235*e1997b9aSAndroid Build Coastguard Worker ) -> Result<StorageStats> { 1236*e1997b9aSAndroid Build Coastguard Worker self.do_table_size_query( 1237*e1997b9aSAndroid Build Coastguard Worker storage_type, 1238*e1997b9aSAndroid Build Coastguard Worker "SELECT pgsize,unused FROM dbstat(?1) 1239*e1997b9aSAndroid Build Coastguard Worker WHERE name=?2 AND aggregate=TRUE;", 1240*e1997b9aSAndroid Build Coastguard Worker &[schema, table], 1241*e1997b9aSAndroid Build Coastguard Worker ) 1242*e1997b9aSAndroid Build Coastguard Worker } 1243*e1997b9aSAndroid Build Coastguard Worker 1244*e1997b9aSAndroid Build Coastguard Worker /// Fetches a storage statistics atom for a given storage type. For storage 1245*e1997b9aSAndroid Build Coastguard Worker /// types that map to a table, information about the table's storage is 1246*e1997b9aSAndroid Build Coastguard Worker /// returned. Requests for storage types that are not DB tables return None. get_storage_stat(&mut self, storage_type: MetricsStorage) -> Result<StorageStats>1247*e1997b9aSAndroid Build Coastguard Worker pub fn get_storage_stat(&mut self, storage_type: MetricsStorage) -> Result<StorageStats> { 1248*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch_millis_with("KeystoreDB::get_storage_stat", 500, storage_type); 1249*e1997b9aSAndroid Build Coastguard Worker 1250*e1997b9aSAndroid Build Coastguard Worker match storage_type { 1251*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::DATABASE => self.get_total_size(), 1252*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_ENTRY => { 1253*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keyentry") 1254*e1997b9aSAndroid Build Coastguard Worker } 1255*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_ENTRY_ID_INDEX => { 1256*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keyentry_id_index") 1257*e1997b9aSAndroid Build Coastguard Worker } 1258*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX => { 1259*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keyentry_domain_namespace_index") 1260*e1997b9aSAndroid Build Coastguard Worker } 1261*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::BLOB_ENTRY => { 1262*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "blobentry") 1263*e1997b9aSAndroid Build Coastguard Worker } 1264*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX => { 1265*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "blobentry_keyentryid_index") 1266*e1997b9aSAndroid Build Coastguard Worker } 1267*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_PARAMETER => { 1268*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keyparameter") 1269*e1997b9aSAndroid Build Coastguard Worker } 1270*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX => { 1271*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keyparameter_keyentryid_index") 1272*e1997b9aSAndroid Build Coastguard Worker } 1273*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_METADATA => { 1274*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keymetadata") 1275*e1997b9aSAndroid Build Coastguard Worker } 1276*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX => { 1277*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "keymetadata_keyentryid_index") 1278*e1997b9aSAndroid Build Coastguard Worker } 1279*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::GRANT => self.get_table_size(storage_type, "persistent", "grant"), 1280*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::AUTH_TOKEN => { 1281*e1997b9aSAndroid Build Coastguard Worker // Since the table is actually a BTreeMap now, unused_size is not meaningfully 1282*e1997b9aSAndroid Build Coastguard Worker // reportable 1283*e1997b9aSAndroid Build Coastguard Worker // Size provided is only an approximation 1284*e1997b9aSAndroid Build Coastguard Worker Ok(StorageStats { 1285*e1997b9aSAndroid Build Coastguard Worker storage_type, 1286*e1997b9aSAndroid Build Coastguard Worker size: (self.perboot.auth_tokens_len() * std::mem::size_of::<AuthTokenEntry>()) 1287*e1997b9aSAndroid Build Coastguard Worker as i32, 1288*e1997b9aSAndroid Build Coastguard Worker unused_size: 0, 1289*e1997b9aSAndroid Build Coastguard Worker }) 1290*e1997b9aSAndroid Build Coastguard Worker } 1291*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::BLOB_METADATA => { 1292*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "blobmetadata") 1293*e1997b9aSAndroid Build Coastguard Worker } 1294*e1997b9aSAndroid Build Coastguard Worker MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX => { 1295*e1997b9aSAndroid Build Coastguard Worker self.get_table_size(storage_type, "persistent", "blobmetadata_blobentryid_index") 1296*e1997b9aSAndroid Build Coastguard Worker } 1297*e1997b9aSAndroid Build Coastguard Worker _ => Err(anyhow::Error::msg(format!("Unsupported storage type: {}", storage_type.0))), 1298*e1997b9aSAndroid Build Coastguard Worker } 1299*e1997b9aSAndroid Build Coastguard Worker } 1300*e1997b9aSAndroid Build Coastguard Worker 1301*e1997b9aSAndroid Build Coastguard Worker /// This function is intended to be used by the garbage collector. 1302*e1997b9aSAndroid Build Coastguard Worker /// It deletes the blobs given by `blob_ids_to_delete`. It then tries to find up to `max_blobs` 1303*e1997b9aSAndroid Build Coastguard Worker /// superseded key blobs that might need special handling by the garbage collector. 1304*e1997b9aSAndroid Build Coastguard Worker /// If no further superseded blobs can be found it deletes all other superseded blobs that don't 1305*e1997b9aSAndroid Build Coastguard Worker /// need special handling and returns None. handle_next_superseded_blobs( &mut self, blob_ids_to_delete: &[i64], max_blobs: usize, ) -> Result<Vec<SupersededBlob>>1306*e1997b9aSAndroid Build Coastguard Worker pub fn handle_next_superseded_blobs( 1307*e1997b9aSAndroid Build Coastguard Worker &mut self, 1308*e1997b9aSAndroid Build Coastguard Worker blob_ids_to_delete: &[i64], 1309*e1997b9aSAndroid Build Coastguard Worker max_blobs: usize, 1310*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Vec<SupersededBlob>> { 1311*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::handle_next_superseded_blob"); 1312*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_handle_next_superseded_blob"), |tx| { 1313*e1997b9aSAndroid Build Coastguard Worker // Delete the given blobs. 1314*e1997b9aSAndroid Build Coastguard Worker for blob_id in blob_ids_to_delete { 1315*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1316*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.blobmetadata WHERE blobentryid = ?;", 1317*e1997b9aSAndroid Build Coastguard Worker params![blob_id], 1318*e1997b9aSAndroid Build Coastguard Worker ) 1319*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to delete blob metadata: {:?}", blob_id))?; 1320*e1997b9aSAndroid Build Coastguard Worker tx.execute("DELETE FROM persistent.blobentry WHERE id = ?;", params![blob_id]) 1321*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to delete blob: {:?}", blob_id))?; 1322*e1997b9aSAndroid Build Coastguard Worker } 1323*e1997b9aSAndroid Build Coastguard Worker 1324*e1997b9aSAndroid Build Coastguard Worker Self::cleanup_unreferenced(tx).context("Trying to cleanup unreferenced.")?; 1325*e1997b9aSAndroid Build Coastguard Worker 1326*e1997b9aSAndroid Build Coastguard Worker // Find up to `max_blobs` more out-of-date key blobs, load their metadata and return it. 1327*e1997b9aSAndroid Build Coastguard Worker let result: Vec<(i64, Vec<u8>)> = if keystore2_flags::use_blob_state_column() { 1328*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::handle_next_superseded_blob find_next v2"); 1329*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 1330*e1997b9aSAndroid Build Coastguard Worker .prepare( 1331*e1997b9aSAndroid Build Coastguard Worker "SELECT id, blob FROM persistent.blobentry 1332*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? AND state != ? 1333*e1997b9aSAndroid Build Coastguard Worker LIMIT ?;", 1334*e1997b9aSAndroid Build Coastguard Worker ) 1335*e1997b9aSAndroid Build Coastguard Worker .context("Trying to prepare query for superseded blobs.")?; 1336*e1997b9aSAndroid Build Coastguard Worker 1337*e1997b9aSAndroid Build Coastguard Worker let rows = stmt 1338*e1997b9aSAndroid Build Coastguard Worker .query_map( 1339*e1997b9aSAndroid Build Coastguard Worker params![SubComponentType::KEY_BLOB, BlobState::Current, max_blobs as i64], 1340*e1997b9aSAndroid Build Coastguard Worker |row| Ok((row.get(0)?, row.get(1)?)), 1341*e1997b9aSAndroid Build Coastguard Worker ) 1342*e1997b9aSAndroid Build Coastguard Worker .context("Trying to query superseded blob.")?; 1343*e1997b9aSAndroid Build Coastguard Worker 1344*e1997b9aSAndroid Build Coastguard Worker rows.collect::<Result<Vec<(i64, Vec<u8>)>, rusqlite::Error>>() 1345*e1997b9aSAndroid Build Coastguard Worker .context("Trying to extract superseded blobs.")? 1346*e1997b9aSAndroid Build Coastguard Worker } else { 1347*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::handle_next_superseded_blob find_next v1"); 1348*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 1349*e1997b9aSAndroid Build Coastguard Worker .prepare( 1350*e1997b9aSAndroid Build Coastguard Worker "SELECT id, blob FROM persistent.blobentry 1351*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? 1352*e1997b9aSAndroid Build Coastguard Worker AND ( 1353*e1997b9aSAndroid Build Coastguard Worker id NOT IN ( 1354*e1997b9aSAndroid Build Coastguard Worker SELECT MAX(id) FROM persistent.blobentry 1355*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? 1356*e1997b9aSAndroid Build Coastguard Worker GROUP BY keyentryid, subcomponent_type 1357*e1997b9aSAndroid Build Coastguard Worker ) 1358*e1997b9aSAndroid Build Coastguard Worker OR keyentryid NOT IN (SELECT id FROM persistent.keyentry) 1359*e1997b9aSAndroid Build Coastguard Worker ) LIMIT ?;", 1360*e1997b9aSAndroid Build Coastguard Worker ) 1361*e1997b9aSAndroid Build Coastguard Worker .context("Trying to prepare query for superseded blobs.")?; 1362*e1997b9aSAndroid Build Coastguard Worker 1363*e1997b9aSAndroid Build Coastguard Worker let rows = stmt 1364*e1997b9aSAndroid Build Coastguard Worker .query_map( 1365*e1997b9aSAndroid Build Coastguard Worker params![ 1366*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 1367*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 1368*e1997b9aSAndroid Build Coastguard Worker max_blobs as i64, 1369*e1997b9aSAndroid Build Coastguard Worker ], 1370*e1997b9aSAndroid Build Coastguard Worker |row| Ok((row.get(0)?, row.get(1)?)), 1371*e1997b9aSAndroid Build Coastguard Worker ) 1372*e1997b9aSAndroid Build Coastguard Worker .context("Trying to query superseded blob.")?; 1373*e1997b9aSAndroid Build Coastguard Worker 1374*e1997b9aSAndroid Build Coastguard Worker rows.collect::<Result<Vec<(i64, Vec<u8>)>, rusqlite::Error>>() 1375*e1997b9aSAndroid Build Coastguard Worker .context("Trying to extract superseded blobs.")? 1376*e1997b9aSAndroid Build Coastguard Worker }; 1377*e1997b9aSAndroid Build Coastguard Worker 1378*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::handle_next_superseded_blob load_metadata"); 1379*e1997b9aSAndroid Build Coastguard Worker let result = result 1380*e1997b9aSAndroid Build Coastguard Worker .into_iter() 1381*e1997b9aSAndroid Build Coastguard Worker .map(|(blob_id, blob)| { 1382*e1997b9aSAndroid Build Coastguard Worker Ok(SupersededBlob { 1383*e1997b9aSAndroid Build Coastguard Worker blob_id, 1384*e1997b9aSAndroid Build Coastguard Worker blob, 1385*e1997b9aSAndroid Build Coastguard Worker metadata: BlobMetaData::load_from_db(blob_id, tx)?, 1386*e1997b9aSAndroid Build Coastguard Worker }) 1387*e1997b9aSAndroid Build Coastguard Worker }) 1388*e1997b9aSAndroid Build Coastguard Worker .collect::<Result<Vec<_>>>() 1389*e1997b9aSAndroid Build Coastguard Worker .context("Trying to load blob metadata.")?; 1390*e1997b9aSAndroid Build Coastguard Worker if !result.is_empty() { 1391*e1997b9aSAndroid Build Coastguard Worker return Ok(result).no_gc(); 1392*e1997b9aSAndroid Build Coastguard Worker } 1393*e1997b9aSAndroid Build Coastguard Worker 1394*e1997b9aSAndroid Build Coastguard Worker // We did not find any out-of-date key blobs, so let's remove other types of superseded 1395*e1997b9aSAndroid Build Coastguard Worker // blob in one transaction. 1396*e1997b9aSAndroid Build Coastguard Worker if keystore2_flags::use_blob_state_column() { 1397*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::handle_next_superseded_blob delete v2"); 1398*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1399*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.blobentry 1400*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type != ? AND state != ?;", 1401*e1997b9aSAndroid Build Coastguard Worker params![SubComponentType::KEY_BLOB, BlobState::Current], 1402*e1997b9aSAndroid Build Coastguard Worker ) 1403*e1997b9aSAndroid Build Coastguard Worker .context("Trying to purge out-of-date blobs (other than keyblobs)")?; 1404*e1997b9aSAndroid Build Coastguard Worker } else { 1405*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::handle_next_superseded_blob delete v1"); 1406*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1407*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.blobentry 1408*e1997b9aSAndroid Build Coastguard Worker WHERE NOT subcomponent_type = ? 1409*e1997b9aSAndroid Build Coastguard Worker AND ( 1410*e1997b9aSAndroid Build Coastguard Worker id NOT IN ( 1411*e1997b9aSAndroid Build Coastguard Worker SELECT MAX(id) FROM persistent.blobentry 1412*e1997b9aSAndroid Build Coastguard Worker WHERE NOT subcomponent_type = ? 1413*e1997b9aSAndroid Build Coastguard Worker GROUP BY keyentryid, subcomponent_type 1414*e1997b9aSAndroid Build Coastguard Worker ) OR keyentryid NOT IN (SELECT id FROM persistent.keyentry) 1415*e1997b9aSAndroid Build Coastguard Worker );", 1416*e1997b9aSAndroid Build Coastguard Worker params![SubComponentType::KEY_BLOB, SubComponentType::KEY_BLOB], 1417*e1997b9aSAndroid Build Coastguard Worker ) 1418*e1997b9aSAndroid Build Coastguard Worker .context("Trying to purge superseded blobs.")?; 1419*e1997b9aSAndroid Build Coastguard Worker } 1420*e1997b9aSAndroid Build Coastguard Worker 1421*e1997b9aSAndroid Build Coastguard Worker Ok(vec![]).no_gc() 1422*e1997b9aSAndroid Build Coastguard Worker }) 1423*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1424*e1997b9aSAndroid Build Coastguard Worker } 1425*e1997b9aSAndroid Build Coastguard Worker 1426*e1997b9aSAndroid Build Coastguard Worker /// This maintenance function should be called only once before the database is used for the 1427*e1997b9aSAndroid Build Coastguard Worker /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state. 1428*e1997b9aSAndroid Build Coastguard Worker /// The function transitions all key entries from Existing to Unreferenced unconditionally and 1429*e1997b9aSAndroid Build Coastguard Worker /// returns the number of rows affected. If this returns a value greater than 0, it means that 1430*e1997b9aSAndroid Build Coastguard Worker /// Keystore crashed at some point during key generation. Callers may want to log such 1431*e1997b9aSAndroid Build Coastguard Worker /// occurrences. 1432*e1997b9aSAndroid Build Coastguard Worker /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made 1433*e1997b9aSAndroid Build Coastguard Worker /// it to `KeyLifeCycle::Live` may have grants. cleanup_leftovers(&mut self) -> Result<usize>1434*e1997b9aSAndroid Build Coastguard Worker pub fn cleanup_leftovers(&mut self) -> Result<usize> { 1435*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::cleanup_leftovers"); 1436*e1997b9aSAndroid Build Coastguard Worker 1437*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_cleanup_leftovers"), |tx| { 1438*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1439*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.keyentry SET state = ? WHERE state = ?;", 1440*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing], 1441*e1997b9aSAndroid Build Coastguard Worker ) 1442*e1997b9aSAndroid Build Coastguard Worker .context("Failed to execute query.") 1443*e1997b9aSAndroid Build Coastguard Worker .need_gc() 1444*e1997b9aSAndroid Build Coastguard Worker }) 1445*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1446*e1997b9aSAndroid Build Coastguard Worker } 1447*e1997b9aSAndroid Build Coastguard Worker 1448*e1997b9aSAndroid Build Coastguard Worker /// 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>1449*e1997b9aSAndroid Build Coastguard Worker pub fn key_exists( 1450*e1997b9aSAndroid Build Coastguard Worker &mut self, 1451*e1997b9aSAndroid Build Coastguard Worker domain: Domain, 1452*e1997b9aSAndroid Build Coastguard Worker nspace: i64, 1453*e1997b9aSAndroid Build Coastguard Worker alias: &str, 1454*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 1455*e1997b9aSAndroid Build Coastguard Worker ) -> Result<bool> { 1456*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::key_exists"); 1457*e1997b9aSAndroid Build Coastguard Worker 1458*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_key_exists"), |tx| { 1459*e1997b9aSAndroid Build Coastguard Worker let key_descriptor = 1460*e1997b9aSAndroid Build Coastguard Worker KeyDescriptor { domain, nspace, alias: Some(alias.to_string()), blob: None }; 1461*e1997b9aSAndroid Build Coastguard Worker let result = Self::load_key_entry_id(tx, &key_descriptor, key_type); 1462*e1997b9aSAndroid Build Coastguard Worker match result { 1463*e1997b9aSAndroid Build Coastguard Worker Ok(_) => Ok(true), 1464*e1997b9aSAndroid Build Coastguard Worker Err(error) => match error.root_cause().downcast_ref::<KsError>() { 1465*e1997b9aSAndroid Build Coastguard Worker Some(KsError::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(false), 1466*e1997b9aSAndroid Build Coastguard Worker _ => Err(error).context(ks_err!("Failed to find if the key exists.")), 1467*e1997b9aSAndroid Build Coastguard Worker }, 1468*e1997b9aSAndroid Build Coastguard Worker } 1469*e1997b9aSAndroid Build Coastguard Worker .no_gc() 1470*e1997b9aSAndroid Build Coastguard Worker }) 1471*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1472*e1997b9aSAndroid Build Coastguard Worker } 1473*e1997b9aSAndroid Build Coastguard Worker 1474*e1997b9aSAndroid Build Coastguard Worker /// 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>1475*e1997b9aSAndroid Build Coastguard Worker pub fn store_super_key( 1476*e1997b9aSAndroid Build Coastguard Worker &mut self, 1477*e1997b9aSAndroid Build Coastguard Worker user_id: u32, 1478*e1997b9aSAndroid Build Coastguard Worker key_type: &SuperKeyType, 1479*e1997b9aSAndroid Build Coastguard Worker blob: &[u8], 1480*e1997b9aSAndroid Build Coastguard Worker blob_metadata: &BlobMetaData, 1481*e1997b9aSAndroid Build Coastguard Worker key_metadata: &KeyMetaData, 1482*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyEntry> { 1483*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::store_super_key"); 1484*e1997b9aSAndroid Build Coastguard Worker 1485*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_store_super_key"), |tx| { 1486*e1997b9aSAndroid Build Coastguard Worker let key_id = Self::insert_with_retry(|id| { 1487*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1488*e1997b9aSAndroid Build Coastguard Worker "INSERT into persistent.keyentry 1489*e1997b9aSAndroid Build Coastguard Worker (id, key_type, domain, namespace, alias, state, km_uuid) 1490*e1997b9aSAndroid Build Coastguard Worker VALUES(?, ?, ?, ?, ?, ?, ?);", 1491*e1997b9aSAndroid Build Coastguard Worker params![ 1492*e1997b9aSAndroid Build Coastguard Worker id, 1493*e1997b9aSAndroid Build Coastguard Worker KeyType::Super, 1494*e1997b9aSAndroid Build Coastguard Worker Domain::APP.0, 1495*e1997b9aSAndroid Build Coastguard Worker user_id as i64, 1496*e1997b9aSAndroid Build Coastguard Worker key_type.alias, 1497*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Live, 1498*e1997b9aSAndroid Build Coastguard Worker &KEYSTORE_UUID, 1499*e1997b9aSAndroid Build Coastguard Worker ], 1500*e1997b9aSAndroid Build Coastguard Worker ) 1501*e1997b9aSAndroid Build Coastguard Worker }) 1502*e1997b9aSAndroid Build Coastguard Worker .context("Failed to insert into keyentry table.")?; 1503*e1997b9aSAndroid Build Coastguard Worker 1504*e1997b9aSAndroid Build Coastguard Worker key_metadata.store_in_db(key_id, tx).context("KeyMetaData::store_in_db failed")?; 1505*e1997b9aSAndroid Build Coastguard Worker 1506*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal( 1507*e1997b9aSAndroid Build Coastguard Worker tx, 1508*e1997b9aSAndroid Build Coastguard Worker key_id, 1509*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 1510*e1997b9aSAndroid Build Coastguard Worker Some(blob), 1511*e1997b9aSAndroid Build Coastguard Worker Some(blob_metadata), 1512*e1997b9aSAndroid Build Coastguard Worker ) 1513*e1997b9aSAndroid Build Coastguard Worker .context("Failed to store key blob.")?; 1514*e1997b9aSAndroid Build Coastguard Worker 1515*e1997b9aSAndroid Build Coastguard Worker Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id) 1516*e1997b9aSAndroid Build Coastguard Worker .context("Trying to load key components.") 1517*e1997b9aSAndroid Build Coastguard Worker .no_gc() 1518*e1997b9aSAndroid Build Coastguard Worker }) 1519*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1520*e1997b9aSAndroid Build Coastguard Worker } 1521*e1997b9aSAndroid Build Coastguard Worker 1522*e1997b9aSAndroid Build Coastguard Worker /// Loads super key of a given user, if exists load_super_key( &mut self, key_type: &SuperKeyType, user_id: u32, ) -> Result<Option<(KeyIdGuard, KeyEntry)>>1523*e1997b9aSAndroid Build Coastguard Worker pub fn load_super_key( 1524*e1997b9aSAndroid Build Coastguard Worker &mut self, 1525*e1997b9aSAndroid Build Coastguard Worker key_type: &SuperKeyType, 1526*e1997b9aSAndroid Build Coastguard Worker user_id: u32, 1527*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Option<(KeyIdGuard, KeyEntry)>> { 1528*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::load_super_key"); 1529*e1997b9aSAndroid Build Coastguard Worker 1530*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_load_super_key"), |tx| { 1531*e1997b9aSAndroid Build Coastguard Worker let key_descriptor = KeyDescriptor { 1532*e1997b9aSAndroid Build Coastguard Worker domain: Domain::APP, 1533*e1997b9aSAndroid Build Coastguard Worker nspace: user_id as i64, 1534*e1997b9aSAndroid Build Coastguard Worker alias: Some(key_type.alias.into()), 1535*e1997b9aSAndroid Build Coastguard Worker blob: None, 1536*e1997b9aSAndroid Build Coastguard Worker }; 1537*e1997b9aSAndroid Build Coastguard Worker let id = Self::load_key_entry_id(tx, &key_descriptor, KeyType::Super); 1538*e1997b9aSAndroid Build Coastguard Worker match id { 1539*e1997b9aSAndroid Build Coastguard Worker Ok(id) => { 1540*e1997b9aSAndroid Build Coastguard Worker let key_entry = Self::load_key_components(tx, KeyEntryLoadBits::KM, id) 1541*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to load key entry."))?; 1542*e1997b9aSAndroid Build Coastguard Worker Ok(Some((KEY_ID_LOCK.get(id), key_entry))) 1543*e1997b9aSAndroid Build Coastguard Worker } 1544*e1997b9aSAndroid Build Coastguard Worker Err(error) => match error.root_cause().downcast_ref::<KsError>() { 1545*e1997b9aSAndroid Build Coastguard Worker Some(KsError::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None), 1546*e1997b9aSAndroid Build Coastguard Worker _ => Err(error).context(ks_err!()), 1547*e1997b9aSAndroid Build Coastguard Worker }, 1548*e1997b9aSAndroid Build Coastguard Worker } 1549*e1997b9aSAndroid Build Coastguard Worker .no_gc() 1550*e1997b9aSAndroid Build Coastguard Worker }) 1551*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1552*e1997b9aSAndroid Build Coastguard Worker } 1553*e1997b9aSAndroid Build Coastguard Worker 1554*e1997b9aSAndroid Build Coastguard Worker /// Creates a transaction with the given behavior and executes f with the new transaction. 1555*e1997b9aSAndroid Build Coastguard Worker /// The transaction is committed only if f returns Ok and retried if DatabaseBusy 1556*e1997b9aSAndroid Build Coastguard Worker /// or DatabaseLocked is encountered. with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T> where F: Fn(&Transaction) -> Result<(bool, T)>,1557*e1997b9aSAndroid Build Coastguard Worker fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T> 1558*e1997b9aSAndroid Build Coastguard Worker where 1559*e1997b9aSAndroid Build Coastguard Worker F: Fn(&Transaction) -> Result<(bool, T)>, 1560*e1997b9aSAndroid Build Coastguard Worker { 1561*e1997b9aSAndroid Build Coastguard Worker let name = behavior.name(); 1562*e1997b9aSAndroid Build Coastguard Worker loop { 1563*e1997b9aSAndroid Build Coastguard Worker let result = self 1564*e1997b9aSAndroid Build Coastguard Worker .conn 1565*e1997b9aSAndroid Build Coastguard Worker .transaction_with_behavior(behavior.into()) 1566*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1567*e1997b9aSAndroid Build Coastguard Worker .and_then(|tx| { 1568*e1997b9aSAndroid Build Coastguard Worker let _wp = name.map(wd::watch); 1569*e1997b9aSAndroid Build Coastguard Worker f(&tx).map(|result| (result, tx)) 1570*e1997b9aSAndroid Build Coastguard Worker }) 1571*e1997b9aSAndroid Build Coastguard Worker .and_then(|(result, tx)| { 1572*e1997b9aSAndroid Build Coastguard Worker tx.commit().context(ks_err!("Failed to commit transaction."))?; 1573*e1997b9aSAndroid Build Coastguard Worker Ok(result) 1574*e1997b9aSAndroid Build Coastguard Worker }); 1575*e1997b9aSAndroid Build Coastguard Worker match result { 1576*e1997b9aSAndroid Build Coastguard Worker Ok(result) => break Ok(result), 1577*e1997b9aSAndroid Build Coastguard Worker Err(e) => { 1578*e1997b9aSAndroid Build Coastguard Worker if Self::is_locked_error(&e) { 1579*e1997b9aSAndroid Build Coastguard Worker std::thread::sleep(DB_BUSY_RETRY_INTERVAL); 1580*e1997b9aSAndroid Build Coastguard Worker continue; 1581*e1997b9aSAndroid Build Coastguard Worker } else { 1582*e1997b9aSAndroid Build Coastguard Worker return Err(e).context(ks_err!()); 1583*e1997b9aSAndroid Build Coastguard Worker } 1584*e1997b9aSAndroid Build Coastguard Worker } 1585*e1997b9aSAndroid Build Coastguard Worker } 1586*e1997b9aSAndroid Build Coastguard Worker } 1587*e1997b9aSAndroid Build Coastguard Worker .map(|(need_gc, result)| { 1588*e1997b9aSAndroid Build Coastguard Worker if need_gc { 1589*e1997b9aSAndroid Build Coastguard Worker if let Some(ref gc) = self.gc { 1590*e1997b9aSAndroid Build Coastguard Worker gc.notify_gc(); 1591*e1997b9aSAndroid Build Coastguard Worker } 1592*e1997b9aSAndroid Build Coastguard Worker } 1593*e1997b9aSAndroid Build Coastguard Worker result 1594*e1997b9aSAndroid Build Coastguard Worker }) 1595*e1997b9aSAndroid Build Coastguard Worker } 1596*e1997b9aSAndroid Build Coastguard Worker is_locked_error(e: &anyhow::Error) -> bool1597*e1997b9aSAndroid Build Coastguard Worker fn is_locked_error(e: &anyhow::Error) -> bool { 1598*e1997b9aSAndroid Build Coastguard Worker matches!( 1599*e1997b9aSAndroid Build Coastguard Worker e.root_cause().downcast_ref::<rusqlite::ffi::Error>(), 1600*e1997b9aSAndroid Build Coastguard Worker Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseBusy, .. }) 1601*e1997b9aSAndroid Build Coastguard Worker | Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseLocked, .. }) 1602*e1997b9aSAndroid Build Coastguard Worker ) 1603*e1997b9aSAndroid Build Coastguard Worker } 1604*e1997b9aSAndroid Build Coastguard Worker create_key_entry_internal( tx: &Transaction, domain: &Domain, namespace: &i64, key_type: KeyType, km_uuid: &Uuid, ) -> Result<KeyIdGuard>1605*e1997b9aSAndroid Build Coastguard Worker fn create_key_entry_internal( 1606*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 1607*e1997b9aSAndroid Build Coastguard Worker domain: &Domain, 1608*e1997b9aSAndroid Build Coastguard Worker namespace: &i64, 1609*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 1610*e1997b9aSAndroid Build Coastguard Worker km_uuid: &Uuid, 1611*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> { 1612*e1997b9aSAndroid Build Coastguard Worker match *domain { 1613*e1997b9aSAndroid Build Coastguard Worker Domain::APP | Domain::SELINUX => {} 1614*e1997b9aSAndroid Build Coastguard Worker _ => { 1615*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::sys()) 1616*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Domain {:?} must be either App or SELinux.", domain)); 1617*e1997b9aSAndroid Build Coastguard Worker } 1618*e1997b9aSAndroid Build Coastguard Worker } 1619*e1997b9aSAndroid Build Coastguard Worker Ok(KEY_ID_LOCK.get( 1620*e1997b9aSAndroid Build Coastguard Worker Self::insert_with_retry(|id| { 1621*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1622*e1997b9aSAndroid Build Coastguard Worker "INSERT into persistent.keyentry 1623*e1997b9aSAndroid Build Coastguard Worker (id, key_type, domain, namespace, alias, state, km_uuid) 1624*e1997b9aSAndroid Build Coastguard Worker VALUES(?, ?, ?, ?, NULL, ?, ?);", 1625*e1997b9aSAndroid Build Coastguard Worker params![ 1626*e1997b9aSAndroid Build Coastguard Worker id, 1627*e1997b9aSAndroid Build Coastguard Worker key_type, 1628*e1997b9aSAndroid Build Coastguard Worker domain.0 as u32, 1629*e1997b9aSAndroid Build Coastguard Worker *namespace, 1630*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Existing, 1631*e1997b9aSAndroid Build Coastguard Worker km_uuid, 1632*e1997b9aSAndroid Build Coastguard Worker ], 1633*e1997b9aSAndroid Build Coastguard Worker ) 1634*e1997b9aSAndroid Build Coastguard Worker }) 1635*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())?, 1636*e1997b9aSAndroid Build Coastguard Worker )) 1637*e1997b9aSAndroid Build Coastguard Worker } 1638*e1997b9aSAndroid Build Coastguard Worker 1639*e1997b9aSAndroid Build Coastguard Worker /// Set a new blob and associates it with the given key id. Each blob 1640*e1997b9aSAndroid Build Coastguard Worker /// has a sub component type. 1641*e1997b9aSAndroid Build Coastguard Worker /// Each key can have one of each sub component type associated. If more 1642*e1997b9aSAndroid Build Coastguard Worker /// are added only the most recent can be retrieved, and superseded blobs 1643*e1997b9aSAndroid Build Coastguard Worker /// will get garbage collected. 1644*e1997b9aSAndroid Build Coastguard Worker /// Components SubComponentType::CERT and SubComponentType::CERT_CHAIN can be 1645*e1997b9aSAndroid Build Coastguard Worker /// removed by setting blob to None. set_blob( &mut self, key_id: &KeyIdGuard, sc_type: SubComponentType, blob: Option<&[u8]>, blob_metadata: Option<&BlobMetaData>, ) -> Result<()>1646*e1997b9aSAndroid Build Coastguard Worker pub fn set_blob( 1647*e1997b9aSAndroid Build Coastguard Worker &mut self, 1648*e1997b9aSAndroid Build Coastguard Worker key_id: &KeyIdGuard, 1649*e1997b9aSAndroid Build Coastguard Worker sc_type: SubComponentType, 1650*e1997b9aSAndroid Build Coastguard Worker blob: Option<&[u8]>, 1651*e1997b9aSAndroid Build Coastguard Worker blob_metadata: Option<&BlobMetaData>, 1652*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> { 1653*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::set_blob"); 1654*e1997b9aSAndroid Build Coastguard Worker 1655*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_set_blob"), |tx| { 1656*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal(tx, key_id.0, sc_type, blob, blob_metadata).need_gc() 1657*e1997b9aSAndroid Build Coastguard Worker }) 1658*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1659*e1997b9aSAndroid Build Coastguard Worker } 1660*e1997b9aSAndroid Build Coastguard Worker 1661*e1997b9aSAndroid Build Coastguard Worker /// Why would we insert a deleted blob? This weird function is for the purpose of legacy 1662*e1997b9aSAndroid Build Coastguard Worker /// key migration in the case where we bulk delete all the keys of an app or even a user. 1663*e1997b9aSAndroid Build Coastguard Worker /// We use this to insert key blobs into the database which can then be garbage collected 1664*e1997b9aSAndroid Build Coastguard Worker /// lazily by the key garbage collector. set_deleted_blob(&mut self, blob: &[u8], blob_metadata: &BlobMetaData) -> Result<()>1665*e1997b9aSAndroid Build Coastguard Worker pub fn set_deleted_blob(&mut self, blob: &[u8], blob_metadata: &BlobMetaData) -> Result<()> { 1666*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::set_deleted_blob"); 1667*e1997b9aSAndroid Build Coastguard Worker 1668*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_set_deleted_blob"), |tx| { 1669*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal( 1670*e1997b9aSAndroid Build Coastguard Worker tx, 1671*e1997b9aSAndroid Build Coastguard Worker Self::UNASSIGNED_KEY_ID, 1672*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 1673*e1997b9aSAndroid Build Coastguard Worker Some(blob), 1674*e1997b9aSAndroid Build Coastguard Worker Some(blob_metadata), 1675*e1997b9aSAndroid Build Coastguard Worker ) 1676*e1997b9aSAndroid Build Coastguard Worker .need_gc() 1677*e1997b9aSAndroid Build Coastguard Worker }) 1678*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1679*e1997b9aSAndroid Build Coastguard Worker } 1680*e1997b9aSAndroid Build Coastguard Worker set_blob_internal( tx: &Transaction, key_id: i64, sc_type: SubComponentType, blob: Option<&[u8]>, blob_metadata: Option<&BlobMetaData>, ) -> Result<()>1681*e1997b9aSAndroid Build Coastguard Worker fn set_blob_internal( 1682*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 1683*e1997b9aSAndroid Build Coastguard Worker key_id: i64, 1684*e1997b9aSAndroid Build Coastguard Worker sc_type: SubComponentType, 1685*e1997b9aSAndroid Build Coastguard Worker blob: Option<&[u8]>, 1686*e1997b9aSAndroid Build Coastguard Worker blob_metadata: Option<&BlobMetaData>, 1687*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> { 1688*e1997b9aSAndroid Build Coastguard Worker match (blob, sc_type) { 1689*e1997b9aSAndroid Build Coastguard Worker (Some(blob), _) => { 1690*e1997b9aSAndroid Build Coastguard Worker // Mark any previous blobentry(s) of the same type for the same key as superseded. 1691*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1692*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.blobentry SET state = ? 1693*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ? AND subcomponent_type = ?", 1694*e1997b9aSAndroid Build Coastguard Worker params![BlobState::Superseded, key_id, sc_type], 1695*e1997b9aSAndroid Build Coastguard Worker ) 1696*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!( 1697*e1997b9aSAndroid Build Coastguard Worker "Failed to mark prior {sc_type:?} blobentrys for {key_id} as superseded" 1698*e1997b9aSAndroid Build Coastguard Worker ))?; 1699*e1997b9aSAndroid Build Coastguard Worker 1700*e1997b9aSAndroid Build Coastguard Worker // Now insert the new, un-superseded, blob. (If this fails, the marking of 1701*e1997b9aSAndroid Build Coastguard Worker // old blobs as superseded will be rolled back, because we're inside a 1702*e1997b9aSAndroid Build Coastguard Worker // transaction.) 1703*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1704*e1997b9aSAndroid Build Coastguard Worker "INSERT INTO persistent.blobentry 1705*e1997b9aSAndroid Build Coastguard Worker (subcomponent_type, keyentryid, blob) VALUES (?, ?, ?);", 1706*e1997b9aSAndroid Build Coastguard Worker params![sc_type, key_id, blob], 1707*e1997b9aSAndroid Build Coastguard Worker ) 1708*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to insert blob."))?; 1709*e1997b9aSAndroid Build Coastguard Worker 1710*e1997b9aSAndroid Build Coastguard Worker if let Some(blob_metadata) = blob_metadata { 1711*e1997b9aSAndroid Build Coastguard Worker let blob_id = tx 1712*e1997b9aSAndroid Build Coastguard Worker .query_row("SELECT MAX(id) FROM persistent.blobentry;", [], |row| { 1713*e1997b9aSAndroid Build Coastguard Worker row.get(0) 1714*e1997b9aSAndroid Build Coastguard Worker }) 1715*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to get new blob id."))?; 1716*e1997b9aSAndroid Build Coastguard Worker 1717*e1997b9aSAndroid Build Coastguard Worker blob_metadata 1718*e1997b9aSAndroid Build Coastguard Worker .store_in_db(blob_id, tx) 1719*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to store blob metadata."))?; 1720*e1997b9aSAndroid Build Coastguard Worker } 1721*e1997b9aSAndroid Build Coastguard Worker } 1722*e1997b9aSAndroid Build Coastguard Worker (None, SubComponentType::CERT) | (None, SubComponentType::CERT_CHAIN) => { 1723*e1997b9aSAndroid Build Coastguard Worker tx.execute( 1724*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.blobentry 1725*e1997b9aSAndroid Build Coastguard Worker WHERE subcomponent_type = ? AND keyentryid = ?;", 1726*e1997b9aSAndroid Build Coastguard Worker params![sc_type, key_id], 1727*e1997b9aSAndroid Build Coastguard Worker ) 1728*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to delete blob."))?; 1729*e1997b9aSAndroid Build Coastguard Worker } 1730*e1997b9aSAndroid Build Coastguard Worker (None, _) => { 1731*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::sys()) 1732*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Other blobs cannot be deleted in this way.")); 1733*e1997b9aSAndroid Build Coastguard Worker } 1734*e1997b9aSAndroid Build Coastguard Worker } 1735*e1997b9aSAndroid Build Coastguard Worker Ok(()) 1736*e1997b9aSAndroid Build Coastguard Worker } 1737*e1997b9aSAndroid Build Coastguard Worker 1738*e1997b9aSAndroid Build Coastguard Worker /// Inserts a collection of key parameters into the `persistent.keyparameter` table 1739*e1997b9aSAndroid Build Coastguard Worker /// and associates them with the given `key_id`. 1740*e1997b9aSAndroid Build Coastguard Worker #[cfg(test)] insert_keyparameter(&mut self, key_id: &KeyIdGuard, params: &[KeyParameter]) -> Result<()>1741*e1997b9aSAndroid Build Coastguard Worker fn insert_keyparameter(&mut self, key_id: &KeyIdGuard, params: &[KeyParameter]) -> Result<()> { 1742*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_insert_keyparameter"), |tx| { 1743*e1997b9aSAndroid Build Coastguard Worker Self::insert_keyparameter_internal(tx, key_id, params).no_gc() 1744*e1997b9aSAndroid Build Coastguard Worker }) 1745*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1746*e1997b9aSAndroid Build Coastguard Worker } 1747*e1997b9aSAndroid Build Coastguard Worker insert_keyparameter_internal( tx: &Transaction, key_id: &KeyIdGuard, params: &[KeyParameter], ) -> Result<()>1748*e1997b9aSAndroid Build Coastguard Worker fn insert_keyparameter_internal( 1749*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 1750*e1997b9aSAndroid Build Coastguard Worker key_id: &KeyIdGuard, 1751*e1997b9aSAndroid Build Coastguard Worker params: &[KeyParameter], 1752*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> { 1753*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 1754*e1997b9aSAndroid Build Coastguard Worker .prepare( 1755*e1997b9aSAndroid Build Coastguard Worker "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level) 1756*e1997b9aSAndroid Build Coastguard Worker VALUES (?, ?, ?, ?);", 1757*e1997b9aSAndroid Build Coastguard Worker ) 1758*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to prepare statement."))?; 1759*e1997b9aSAndroid Build Coastguard Worker 1760*e1997b9aSAndroid Build Coastguard Worker for p in params.iter() { 1761*e1997b9aSAndroid Build Coastguard Worker stmt.insert(params![ 1762*e1997b9aSAndroid Build Coastguard Worker key_id.0, 1763*e1997b9aSAndroid Build Coastguard Worker p.get_tag().0, 1764*e1997b9aSAndroid Build Coastguard Worker p.key_parameter_value(), 1765*e1997b9aSAndroid Build Coastguard Worker p.security_level().0 1766*e1997b9aSAndroid Build Coastguard Worker ]) 1767*e1997b9aSAndroid Build Coastguard Worker .with_context(|| ks_err!("Failed to insert {:?}", p))?; 1768*e1997b9aSAndroid Build Coastguard Worker } 1769*e1997b9aSAndroid Build Coastguard Worker Ok(()) 1770*e1997b9aSAndroid Build Coastguard Worker } 1771*e1997b9aSAndroid Build Coastguard Worker 1772*e1997b9aSAndroid Build Coastguard Worker /// Insert a set of key entry specific metadata into the database. 1773*e1997b9aSAndroid Build Coastguard Worker #[cfg(test)] insert_key_metadata(&mut self, key_id: &KeyIdGuard, metadata: &KeyMetaData) -> Result<()>1774*e1997b9aSAndroid Build Coastguard Worker fn insert_key_metadata(&mut self, key_id: &KeyIdGuard, metadata: &KeyMetaData) -> Result<()> { 1775*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_insert_key_metadata"), |tx| { 1776*e1997b9aSAndroid Build Coastguard Worker metadata.store_in_db(key_id.0, tx).no_gc() 1777*e1997b9aSAndroid Build Coastguard Worker }) 1778*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1779*e1997b9aSAndroid Build Coastguard Worker } 1780*e1997b9aSAndroid Build Coastguard Worker 1781*e1997b9aSAndroid Build Coastguard Worker /// Updates the alias column of the given key id `newid` with the given alias, 1782*e1997b9aSAndroid Build Coastguard Worker /// and atomically, removes the alias, domain, and namespace from another row 1783*e1997b9aSAndroid Build Coastguard Worker /// with the same alias-domain-namespace tuple if such row exits. 1784*e1997b9aSAndroid Build Coastguard Worker /// Returns Ok(true) if an old key was marked unreferenced as a hint to the garbage 1785*e1997b9aSAndroid Build Coastguard Worker /// collector. rebind_alias( tx: &Transaction, newid: &KeyIdGuard, alias: &str, domain: &Domain, namespace: &i64, key_type: KeyType, ) -> Result<bool>1786*e1997b9aSAndroid Build Coastguard Worker fn rebind_alias( 1787*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 1788*e1997b9aSAndroid Build Coastguard Worker newid: &KeyIdGuard, 1789*e1997b9aSAndroid Build Coastguard Worker alias: &str, 1790*e1997b9aSAndroid Build Coastguard Worker domain: &Domain, 1791*e1997b9aSAndroid Build Coastguard Worker namespace: &i64, 1792*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 1793*e1997b9aSAndroid Build Coastguard Worker ) -> Result<bool> { 1794*e1997b9aSAndroid Build Coastguard Worker match *domain { 1795*e1997b9aSAndroid Build Coastguard Worker Domain::APP | Domain::SELINUX => {} 1796*e1997b9aSAndroid Build Coastguard Worker _ => { 1797*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::sys()) 1798*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Domain {:?} must be either App or SELinux.", domain)); 1799*e1997b9aSAndroid Build Coastguard Worker } 1800*e1997b9aSAndroid Build Coastguard Worker } 1801*e1997b9aSAndroid Build Coastguard Worker let updated = tx 1802*e1997b9aSAndroid Build Coastguard Worker .execute( 1803*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.keyentry 1804*e1997b9aSAndroid Build Coastguard Worker SET alias = NULL, domain = NULL, namespace = NULL, state = ? 1805*e1997b9aSAndroid Build Coastguard Worker WHERE alias = ? AND domain = ? AND namespace = ? AND key_type = ?;", 1806*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace, key_type], 1807*e1997b9aSAndroid Build Coastguard Worker ) 1808*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to rebind existing entry."))?; 1809*e1997b9aSAndroid Build Coastguard Worker let result = tx 1810*e1997b9aSAndroid Build Coastguard Worker .execute( 1811*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.keyentry 1812*e1997b9aSAndroid Build Coastguard Worker SET alias = ?, state = ? 1813*e1997b9aSAndroid Build Coastguard Worker WHERE id = ? AND domain = ? AND namespace = ? AND state = ? AND key_type = ?;", 1814*e1997b9aSAndroid Build Coastguard Worker params![ 1815*e1997b9aSAndroid Build Coastguard Worker alias, 1816*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Live, 1817*e1997b9aSAndroid Build Coastguard Worker newid.0, 1818*e1997b9aSAndroid Build Coastguard Worker domain.0 as u32, 1819*e1997b9aSAndroid Build Coastguard Worker *namespace, 1820*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Existing, 1821*e1997b9aSAndroid Build Coastguard Worker key_type, 1822*e1997b9aSAndroid Build Coastguard Worker ], 1823*e1997b9aSAndroid Build Coastguard Worker ) 1824*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to set alias."))?; 1825*e1997b9aSAndroid Build Coastguard Worker if result != 1 { 1826*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::sys()).context(ks_err!( 1827*e1997b9aSAndroid Build Coastguard Worker "Expected to update a single entry but instead updated {}.", 1828*e1997b9aSAndroid Build Coastguard Worker result 1829*e1997b9aSAndroid Build Coastguard Worker )); 1830*e1997b9aSAndroid Build Coastguard Worker } 1831*e1997b9aSAndroid Build Coastguard Worker Ok(updated != 0) 1832*e1997b9aSAndroid Build Coastguard Worker } 1833*e1997b9aSAndroid Build Coastguard Worker 1834*e1997b9aSAndroid Build Coastguard Worker /// Moves the key given by KeyIdGuard to the new location at `destination`. If the destination 1835*e1997b9aSAndroid Build Coastguard Worker /// 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<()>1836*e1997b9aSAndroid Build Coastguard Worker pub fn migrate_key_namespace( 1837*e1997b9aSAndroid Build Coastguard Worker &mut self, 1838*e1997b9aSAndroid Build Coastguard Worker key_id_guard: KeyIdGuard, 1839*e1997b9aSAndroid Build Coastguard Worker destination: &KeyDescriptor, 1840*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 1841*e1997b9aSAndroid Build Coastguard Worker check_permission: impl Fn(&KeyDescriptor) -> Result<()>, 1842*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> { 1843*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::migrate_key_namespace"); 1844*e1997b9aSAndroid Build Coastguard Worker 1845*e1997b9aSAndroid Build Coastguard Worker let destination = match destination.domain { 1846*e1997b9aSAndroid Build Coastguard Worker Domain::APP => KeyDescriptor { nspace: caller_uid as i64, ..(*destination).clone() }, 1847*e1997b9aSAndroid Build Coastguard Worker Domain::SELINUX => (*destination).clone(), 1848*e1997b9aSAndroid Build Coastguard Worker domain => { 1849*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 1850*e1997b9aSAndroid Build Coastguard Worker .context(format!("Domain {:?} must be either APP or SELINUX.", domain)); 1851*e1997b9aSAndroid Build Coastguard Worker } 1852*e1997b9aSAndroid Build Coastguard Worker }; 1853*e1997b9aSAndroid Build Coastguard Worker 1854*e1997b9aSAndroid Build Coastguard Worker // Security critical: Must return immediately on failure. Do not remove the '?'; 1855*e1997b9aSAndroid Build Coastguard Worker check_permission(&destination).context(ks_err!("Trying to check permission."))?; 1856*e1997b9aSAndroid Build Coastguard Worker 1857*e1997b9aSAndroid Build Coastguard Worker let alias = destination 1858*e1997b9aSAndroid Build Coastguard Worker .alias 1859*e1997b9aSAndroid Build Coastguard Worker .as_ref() 1860*e1997b9aSAndroid Build Coastguard Worker .ok_or(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 1861*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Alias must be specified."))?; 1862*e1997b9aSAndroid Build Coastguard Worker 1863*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_migrate_key_namespace"), |tx| { 1864*e1997b9aSAndroid Build Coastguard Worker // Query the destination location. If there is a key, the migration request fails. 1865*e1997b9aSAndroid Build Coastguard Worker if tx 1866*e1997b9aSAndroid Build Coastguard Worker .query_row( 1867*e1997b9aSAndroid Build Coastguard Worker "SELECT id FROM persistent.keyentry 1868*e1997b9aSAndroid Build Coastguard Worker WHERE alias = ? AND domain = ? AND namespace = ?;", 1869*e1997b9aSAndroid Build Coastguard Worker params![alias, destination.domain.0, destination.nspace], 1870*e1997b9aSAndroid Build Coastguard Worker |_| Ok(()), 1871*e1997b9aSAndroid Build Coastguard Worker ) 1872*e1997b9aSAndroid Build Coastguard Worker .optional() 1873*e1997b9aSAndroid Build Coastguard Worker .context("Failed to query destination.")? 1874*e1997b9aSAndroid Build Coastguard Worker .is_some() 1875*e1997b9aSAndroid Build Coastguard Worker { 1876*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 1877*e1997b9aSAndroid Build Coastguard Worker .context("Target already exists."); 1878*e1997b9aSAndroid Build Coastguard Worker } 1879*e1997b9aSAndroid Build Coastguard Worker 1880*e1997b9aSAndroid Build Coastguard Worker let updated = tx 1881*e1997b9aSAndroid Build Coastguard Worker .execute( 1882*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.keyentry 1883*e1997b9aSAndroid Build Coastguard Worker SET alias = ?, domain = ?, namespace = ? 1884*e1997b9aSAndroid Build Coastguard Worker WHERE id = ?;", 1885*e1997b9aSAndroid Build Coastguard Worker params![alias, destination.domain.0, destination.nspace, key_id_guard.id()], 1886*e1997b9aSAndroid Build Coastguard Worker ) 1887*e1997b9aSAndroid Build Coastguard Worker .context("Failed to update key entry.")?; 1888*e1997b9aSAndroid Build Coastguard Worker 1889*e1997b9aSAndroid Build Coastguard Worker if updated != 1 { 1890*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::sys()) 1891*e1997b9aSAndroid Build Coastguard Worker .context(format!("Update succeeded, but {} rows were updated.", updated)); 1892*e1997b9aSAndroid Build Coastguard Worker } 1893*e1997b9aSAndroid Build Coastguard Worker Ok(()).no_gc() 1894*e1997b9aSAndroid Build Coastguard Worker }) 1895*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1896*e1997b9aSAndroid Build Coastguard Worker } 1897*e1997b9aSAndroid Build Coastguard Worker 1898*e1997b9aSAndroid Build Coastguard Worker /// Store a new key in a single transaction. 1899*e1997b9aSAndroid Build Coastguard Worker /// The function creates a new key entry, populates the blob, key parameter, and metadata 1900*e1997b9aSAndroid Build Coastguard Worker /// fields, and rebinds the given alias to the new key. 1901*e1997b9aSAndroid Build Coastguard Worker /// The boolean returned is a hint for the garbage collector. If true, a key was replaced, 1902*e1997b9aSAndroid Build Coastguard Worker /// is now unreferenced and needs to be collected. 1903*e1997b9aSAndroid Build Coastguard Worker #[allow(clippy::too_many_arguments)] store_new_key( &mut self, key: &KeyDescriptor, key_type: KeyType, params: &[KeyParameter], blob_info: &BlobInfo, cert_info: &CertificateInfo, metadata: &KeyMetaData, km_uuid: &Uuid, ) -> Result<KeyIdGuard>1904*e1997b9aSAndroid Build Coastguard Worker pub fn store_new_key( 1905*e1997b9aSAndroid Build Coastguard Worker &mut self, 1906*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 1907*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 1908*e1997b9aSAndroid Build Coastguard Worker params: &[KeyParameter], 1909*e1997b9aSAndroid Build Coastguard Worker blob_info: &BlobInfo, 1910*e1997b9aSAndroid Build Coastguard Worker cert_info: &CertificateInfo, 1911*e1997b9aSAndroid Build Coastguard Worker metadata: &KeyMetaData, 1912*e1997b9aSAndroid Build Coastguard Worker km_uuid: &Uuid, 1913*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> { 1914*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::store_new_key"); 1915*e1997b9aSAndroid Build Coastguard Worker 1916*e1997b9aSAndroid Build Coastguard Worker let (alias, domain, namespace) = match key { 1917*e1997b9aSAndroid Build Coastguard Worker KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None } 1918*e1997b9aSAndroid Build Coastguard Worker | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => { 1919*e1997b9aSAndroid Build Coastguard Worker (alias, key.domain, nspace) 1920*e1997b9aSAndroid Build Coastguard Worker } 1921*e1997b9aSAndroid Build Coastguard Worker _ => { 1922*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 1923*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Need alias and domain must be APP or SELINUX.")); 1924*e1997b9aSAndroid Build Coastguard Worker } 1925*e1997b9aSAndroid Build Coastguard Worker }; 1926*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_store_new_key"), |tx| { 1927*e1997b9aSAndroid Build Coastguard Worker let key_id = Self::create_key_entry_internal(tx, &domain, namespace, key_type, km_uuid) 1928*e1997b9aSAndroid Build Coastguard Worker .context("Trying to create new key entry.")?; 1929*e1997b9aSAndroid Build Coastguard Worker let BlobInfo { blob, metadata: blob_metadata, superseded_blob } = *blob_info; 1930*e1997b9aSAndroid Build Coastguard Worker 1931*e1997b9aSAndroid Build Coastguard Worker // In some occasions the key blob is already upgraded during the import. 1932*e1997b9aSAndroid Build Coastguard Worker // In order to make sure it gets properly deleted it is inserted into the 1933*e1997b9aSAndroid Build Coastguard Worker // database here and then immediately replaced by the superseding blob. 1934*e1997b9aSAndroid Build Coastguard Worker // The garbage collector will then subject the blob to deleteKey of the 1935*e1997b9aSAndroid Build Coastguard Worker // KM back end to permanently invalidate the key. 1936*e1997b9aSAndroid Build Coastguard Worker let need_gc = if let Some((blob, blob_metadata)) = superseded_blob { 1937*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal( 1938*e1997b9aSAndroid Build Coastguard Worker tx, 1939*e1997b9aSAndroid Build Coastguard Worker key_id.id(), 1940*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 1941*e1997b9aSAndroid Build Coastguard Worker Some(blob), 1942*e1997b9aSAndroid Build Coastguard Worker Some(blob_metadata), 1943*e1997b9aSAndroid Build Coastguard Worker ) 1944*e1997b9aSAndroid Build Coastguard Worker .context("Trying to insert superseded key blob.")?; 1945*e1997b9aSAndroid Build Coastguard Worker true 1946*e1997b9aSAndroid Build Coastguard Worker } else { 1947*e1997b9aSAndroid Build Coastguard Worker false 1948*e1997b9aSAndroid Build Coastguard Worker }; 1949*e1997b9aSAndroid Build Coastguard Worker 1950*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal( 1951*e1997b9aSAndroid Build Coastguard Worker tx, 1952*e1997b9aSAndroid Build Coastguard Worker key_id.id(), 1953*e1997b9aSAndroid Build Coastguard Worker SubComponentType::KEY_BLOB, 1954*e1997b9aSAndroid Build Coastguard Worker Some(blob), 1955*e1997b9aSAndroid Build Coastguard Worker Some(blob_metadata), 1956*e1997b9aSAndroid Build Coastguard Worker ) 1957*e1997b9aSAndroid Build Coastguard Worker .context("Trying to insert the key blob.")?; 1958*e1997b9aSAndroid Build Coastguard Worker if let Some(cert) = &cert_info.cert { 1959*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal(tx, key_id.id(), SubComponentType::CERT, Some(cert), None) 1960*e1997b9aSAndroid Build Coastguard Worker .context("Trying to insert the certificate.")?; 1961*e1997b9aSAndroid Build Coastguard Worker } 1962*e1997b9aSAndroid Build Coastguard Worker if let Some(cert_chain) = &cert_info.cert_chain { 1963*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal( 1964*e1997b9aSAndroid Build Coastguard Worker tx, 1965*e1997b9aSAndroid Build Coastguard Worker key_id.id(), 1966*e1997b9aSAndroid Build Coastguard Worker SubComponentType::CERT_CHAIN, 1967*e1997b9aSAndroid Build Coastguard Worker Some(cert_chain), 1968*e1997b9aSAndroid Build Coastguard Worker None, 1969*e1997b9aSAndroid Build Coastguard Worker ) 1970*e1997b9aSAndroid Build Coastguard Worker .context("Trying to insert the certificate chain.")?; 1971*e1997b9aSAndroid Build Coastguard Worker } 1972*e1997b9aSAndroid Build Coastguard Worker Self::insert_keyparameter_internal(tx, &key_id, params) 1973*e1997b9aSAndroid Build Coastguard Worker .context("Trying to insert key parameters.")?; 1974*e1997b9aSAndroid Build Coastguard Worker metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?; 1975*e1997b9aSAndroid Build Coastguard Worker let need_gc = Self::rebind_alias(tx, &key_id, alias, &domain, namespace, key_type) 1976*e1997b9aSAndroid Build Coastguard Worker .context("Trying to rebind alias.")? 1977*e1997b9aSAndroid Build Coastguard Worker || need_gc; 1978*e1997b9aSAndroid Build Coastguard Worker Ok(key_id).do_gc(need_gc) 1979*e1997b9aSAndroid Build Coastguard Worker }) 1980*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 1981*e1997b9aSAndroid Build Coastguard Worker } 1982*e1997b9aSAndroid Build Coastguard Worker 1983*e1997b9aSAndroid Build Coastguard Worker /// Store a new certificate 1984*e1997b9aSAndroid Build Coastguard Worker /// The function creates a new key entry, populates the blob field and metadata, and rebinds 1985*e1997b9aSAndroid Build Coastguard Worker /// the given alias to the new cert. store_new_certificate( &mut self, key: &KeyDescriptor, key_type: KeyType, cert: &[u8], km_uuid: &Uuid, ) -> Result<KeyIdGuard>1986*e1997b9aSAndroid Build Coastguard Worker pub fn store_new_certificate( 1987*e1997b9aSAndroid Build Coastguard Worker &mut self, 1988*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 1989*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 1990*e1997b9aSAndroid Build Coastguard Worker cert: &[u8], 1991*e1997b9aSAndroid Build Coastguard Worker km_uuid: &Uuid, 1992*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> { 1993*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::store_new_certificate"); 1994*e1997b9aSAndroid Build Coastguard Worker 1995*e1997b9aSAndroid Build Coastguard Worker let (alias, domain, namespace) = match key { 1996*e1997b9aSAndroid Build Coastguard Worker KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None } 1997*e1997b9aSAndroid Build Coastguard Worker | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => { 1998*e1997b9aSAndroid Build Coastguard Worker (alias, key.domain, nspace) 1999*e1997b9aSAndroid Build Coastguard Worker } 2000*e1997b9aSAndroid Build Coastguard Worker _ => { 2001*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)) 2002*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Need alias and domain must be APP or SELINUX.")); 2003*e1997b9aSAndroid Build Coastguard Worker } 2004*e1997b9aSAndroid Build Coastguard Worker }; 2005*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_store_new_certificate"), |tx| { 2006*e1997b9aSAndroid Build Coastguard Worker let key_id = Self::create_key_entry_internal(tx, &domain, namespace, key_type, km_uuid) 2007*e1997b9aSAndroid Build Coastguard Worker .context("Trying to create new key entry.")?; 2008*e1997b9aSAndroid Build Coastguard Worker 2009*e1997b9aSAndroid Build Coastguard Worker Self::set_blob_internal( 2010*e1997b9aSAndroid Build Coastguard Worker tx, 2011*e1997b9aSAndroid Build Coastguard Worker key_id.id(), 2012*e1997b9aSAndroid Build Coastguard Worker SubComponentType::CERT_CHAIN, 2013*e1997b9aSAndroid Build Coastguard Worker Some(cert), 2014*e1997b9aSAndroid Build Coastguard Worker None, 2015*e1997b9aSAndroid Build Coastguard Worker ) 2016*e1997b9aSAndroid Build Coastguard Worker .context("Trying to insert certificate.")?; 2017*e1997b9aSAndroid Build Coastguard Worker 2018*e1997b9aSAndroid Build Coastguard Worker let mut metadata = KeyMetaData::new(); 2019*e1997b9aSAndroid Build Coastguard Worker metadata.add(KeyMetaEntry::CreationDate( 2020*e1997b9aSAndroid Build Coastguard Worker DateTime::now().context("Trying to make creation time.")?, 2021*e1997b9aSAndroid Build Coastguard Worker )); 2022*e1997b9aSAndroid Build Coastguard Worker 2023*e1997b9aSAndroid Build Coastguard Worker metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?; 2024*e1997b9aSAndroid Build Coastguard Worker 2025*e1997b9aSAndroid Build Coastguard Worker let need_gc = Self::rebind_alias(tx, &key_id, alias, &domain, namespace, key_type) 2026*e1997b9aSAndroid Build Coastguard Worker .context("Trying to rebind alias.")?; 2027*e1997b9aSAndroid Build Coastguard Worker Ok(key_id).do_gc(need_gc) 2028*e1997b9aSAndroid Build Coastguard Worker }) 2029*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2030*e1997b9aSAndroid Build Coastguard Worker } 2031*e1997b9aSAndroid Build Coastguard Worker 2032*e1997b9aSAndroid Build Coastguard Worker // Helper function loading the key_id given the key descriptor 2033*e1997b9aSAndroid Build Coastguard Worker // tuple comprising domain, namespace, and alias. 2034*e1997b9aSAndroid Build Coastguard Worker // Requires a valid transaction. load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64>2035*e1997b9aSAndroid Build Coastguard Worker fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> { 2036*e1997b9aSAndroid Build Coastguard Worker let alias = key 2037*e1997b9aSAndroid Build Coastguard Worker .alias 2038*e1997b9aSAndroid Build Coastguard Worker .as_ref() 2039*e1997b9aSAndroid Build Coastguard Worker .map_or_else(|| Err(KsError::sys()), Ok) 2040*e1997b9aSAndroid Build Coastguard Worker .context("In load_key_entry_id: Alias must be specified.")?; 2041*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2042*e1997b9aSAndroid Build Coastguard Worker .prepare( 2043*e1997b9aSAndroid Build Coastguard Worker "SELECT id FROM persistent.keyentry 2044*e1997b9aSAndroid Build Coastguard Worker WHERE 2045*e1997b9aSAndroid Build Coastguard Worker key_type = ? 2046*e1997b9aSAndroid Build Coastguard Worker AND domain = ? 2047*e1997b9aSAndroid Build Coastguard Worker AND namespace = ? 2048*e1997b9aSAndroid Build Coastguard Worker AND alias = ? 2049*e1997b9aSAndroid Build Coastguard Worker AND state = ?;", 2050*e1997b9aSAndroid Build Coastguard Worker ) 2051*e1997b9aSAndroid Build Coastguard Worker .context("In load_key_entry_id: Failed to select from keyentry table.")?; 2052*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 2053*e1997b9aSAndroid Build Coastguard Worker .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live]) 2054*e1997b9aSAndroid Build Coastguard Worker .context("In load_key_entry_id: Failed to read from keyentry table.")?; 2055*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_one(&mut rows, |row| { 2056*e1997b9aSAndroid Build Coastguard Worker row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)? 2057*e1997b9aSAndroid Build Coastguard Worker .get(0) 2058*e1997b9aSAndroid Build Coastguard Worker .context("Failed to unpack id.") 2059*e1997b9aSAndroid Build Coastguard Worker }) 2060*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2061*e1997b9aSAndroid Build Coastguard Worker } 2062*e1997b9aSAndroid Build Coastguard Worker 2063*e1997b9aSAndroid Build Coastguard Worker /// This helper function completes the access tuple of a key, which is required 2064*e1997b9aSAndroid Build Coastguard Worker /// to perform access control. The strategy depends on the `domain` field in the 2065*e1997b9aSAndroid Build Coastguard Worker /// key descriptor. 2066*e1997b9aSAndroid Build Coastguard Worker /// * Domain::SELINUX: The access tuple is complete and this function only loads 2067*e1997b9aSAndroid Build Coastguard Worker /// the key_id for further processing. 2068*e1997b9aSAndroid Build Coastguard Worker /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid` 2069*e1997b9aSAndroid Build Coastguard Worker /// which serves as the namespace. 2070*e1997b9aSAndroid Build Coastguard Worker /// * Domain::GRANT: The grant table is queried for the `key_id` and the 2071*e1997b9aSAndroid Build Coastguard Worker /// `access_vector`. 2072*e1997b9aSAndroid Build Coastguard Worker /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and 2073*e1997b9aSAndroid Build Coastguard Worker /// `namespace`. 2074*e1997b9aSAndroid Build Coastguard Worker /// 2075*e1997b9aSAndroid Build Coastguard Worker /// In each case the information returned is sufficient to perform the access 2076*e1997b9aSAndroid Build Coastguard Worker /// 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<KeyAccessInfo>2077*e1997b9aSAndroid Build Coastguard Worker fn load_access_tuple( 2078*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 2079*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 2080*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 2081*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 2082*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyAccessInfo> { 2083*e1997b9aSAndroid Build Coastguard Worker match key.domain { 2084*e1997b9aSAndroid Build Coastguard Worker // Domain App or SELinux. In this case we load the key_id from 2085*e1997b9aSAndroid Build Coastguard Worker // the keyentry database for further loading of key components. 2086*e1997b9aSAndroid Build Coastguard Worker // We already have the full access tuple to perform access control. 2087*e1997b9aSAndroid Build Coastguard Worker // The only distinction is that we use the caller_uid instead 2088*e1997b9aSAndroid Build Coastguard Worker // of the caller supplied namespace if the domain field is 2089*e1997b9aSAndroid Build Coastguard Worker // Domain::APP. 2090*e1997b9aSAndroid Build Coastguard Worker Domain::APP | Domain::SELINUX => { 2091*e1997b9aSAndroid Build Coastguard Worker let mut access_key = key.clone(); 2092*e1997b9aSAndroid Build Coastguard Worker if access_key.domain == Domain::APP { 2093*e1997b9aSAndroid Build Coastguard Worker access_key.nspace = caller_uid as i64; 2094*e1997b9aSAndroid Build Coastguard Worker } 2095*e1997b9aSAndroid Build Coastguard Worker let key_id = Self::load_key_entry_id(tx, &access_key, key_type) 2096*e1997b9aSAndroid Build Coastguard Worker .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?; 2097*e1997b9aSAndroid Build Coastguard Worker 2098*e1997b9aSAndroid Build Coastguard Worker Ok(KeyAccessInfo { key_id, descriptor: access_key, vector: None }) 2099*e1997b9aSAndroid Build Coastguard Worker } 2100*e1997b9aSAndroid Build Coastguard Worker 2101*e1997b9aSAndroid Build Coastguard Worker // Domain::GRANT. In this case we load the key_id and the access_vector 2102*e1997b9aSAndroid Build Coastguard Worker // from the grant table. 2103*e1997b9aSAndroid Build Coastguard Worker Domain::GRANT => { 2104*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2105*e1997b9aSAndroid Build Coastguard Worker .prepare( 2106*e1997b9aSAndroid Build Coastguard Worker "SELECT keyentryid, access_vector FROM persistent.grant 2107*e1997b9aSAndroid Build Coastguard Worker WHERE grantee = ? AND id = ? AND 2108*e1997b9aSAndroid Build Coastguard Worker (SELECT state FROM persistent.keyentry WHERE id = keyentryid) = ?;", 2109*e1997b9aSAndroid Build Coastguard Worker ) 2110*e1997b9aSAndroid Build Coastguard Worker .context("Domain::GRANT prepare statement failed")?; 2111*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 2112*e1997b9aSAndroid Build Coastguard Worker .query(params![caller_uid as i64, key.nspace, KeyLifeCycle::Live]) 2113*e1997b9aSAndroid Build Coastguard Worker .context("Domain:Grant: query failed.")?; 2114*e1997b9aSAndroid Build Coastguard Worker let (key_id, access_vector): (i64, i32) = 2115*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_one(&mut rows, |row| { 2116*e1997b9aSAndroid Build Coastguard Worker let r = 2117*e1997b9aSAndroid Build Coastguard Worker row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?; 2118*e1997b9aSAndroid Build Coastguard Worker Ok(( 2119*e1997b9aSAndroid Build Coastguard Worker r.get(0).context("Failed to unpack key_id.")?, 2120*e1997b9aSAndroid Build Coastguard Worker r.get(1).context("Failed to unpack access_vector.")?, 2121*e1997b9aSAndroid Build Coastguard Worker )) 2122*e1997b9aSAndroid Build Coastguard Worker }) 2123*e1997b9aSAndroid Build Coastguard Worker .context("Domain::GRANT.")?; 2124*e1997b9aSAndroid Build Coastguard Worker Ok(KeyAccessInfo { 2125*e1997b9aSAndroid Build Coastguard Worker key_id, 2126*e1997b9aSAndroid Build Coastguard Worker descriptor: key.clone(), 2127*e1997b9aSAndroid Build Coastguard Worker vector: Some(access_vector.into()), 2128*e1997b9aSAndroid Build Coastguard Worker }) 2129*e1997b9aSAndroid Build Coastguard Worker } 2130*e1997b9aSAndroid Build Coastguard Worker 2131*e1997b9aSAndroid Build Coastguard Worker // Domain::KEY_ID. In this case we load the domain and namespace from the 2132*e1997b9aSAndroid Build Coastguard Worker // keyentry database because we need them for access control. 2133*e1997b9aSAndroid Build Coastguard Worker Domain::KEY_ID => { 2134*e1997b9aSAndroid Build Coastguard Worker let (domain, namespace): (Domain, i64) = { 2135*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2136*e1997b9aSAndroid Build Coastguard Worker .prepare( 2137*e1997b9aSAndroid Build Coastguard Worker "SELECT domain, namespace FROM persistent.keyentry 2138*e1997b9aSAndroid Build Coastguard Worker WHERE 2139*e1997b9aSAndroid Build Coastguard Worker id = ? 2140*e1997b9aSAndroid Build Coastguard Worker AND state = ?;", 2141*e1997b9aSAndroid Build Coastguard Worker ) 2142*e1997b9aSAndroid Build Coastguard Worker .context("Domain::KEY_ID: prepare statement failed")?; 2143*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 2144*e1997b9aSAndroid Build Coastguard Worker .query(params![key.nspace, KeyLifeCycle::Live]) 2145*e1997b9aSAndroid Build Coastguard Worker .context("Domain::KEY_ID: query failed.")?; 2146*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_one(&mut rows, |row| { 2147*e1997b9aSAndroid Build Coastguard Worker let r = 2148*e1997b9aSAndroid Build Coastguard Worker row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?; 2149*e1997b9aSAndroid Build Coastguard Worker Ok(( 2150*e1997b9aSAndroid Build Coastguard Worker Domain(r.get(0).context("Failed to unpack domain.")?), 2151*e1997b9aSAndroid Build Coastguard Worker r.get(1).context("Failed to unpack namespace.")?, 2152*e1997b9aSAndroid Build Coastguard Worker )) 2153*e1997b9aSAndroid Build Coastguard Worker }) 2154*e1997b9aSAndroid Build Coastguard Worker .context("Domain::KEY_ID.")? 2155*e1997b9aSAndroid Build Coastguard Worker }; 2156*e1997b9aSAndroid Build Coastguard Worker 2157*e1997b9aSAndroid Build Coastguard Worker // We may use a key by id after loading it by grant. 2158*e1997b9aSAndroid Build Coastguard Worker // In this case we have to check if the caller has a grant for this particular 2159*e1997b9aSAndroid Build Coastguard Worker // key. We can skip this if we already know that the caller is the owner. 2160*e1997b9aSAndroid Build Coastguard Worker // But we cannot know this if domain is anything but App. E.g. in the case 2161*e1997b9aSAndroid Build Coastguard Worker // of Domain::SELINUX we have to speculatively check for grants because we have to 2162*e1997b9aSAndroid Build Coastguard Worker // consult the SEPolicy before we know if the caller is the owner. 2163*e1997b9aSAndroid Build Coastguard Worker let access_vector: Option<KeyPermSet> = 2164*e1997b9aSAndroid Build Coastguard Worker if domain != Domain::APP || namespace != caller_uid as i64 { 2165*e1997b9aSAndroid Build Coastguard Worker let access_vector: Option<i32> = tx 2166*e1997b9aSAndroid Build Coastguard Worker .query_row( 2167*e1997b9aSAndroid Build Coastguard Worker "SELECT access_vector FROM persistent.grant 2168*e1997b9aSAndroid Build Coastguard Worker WHERE grantee = ? AND keyentryid = ?;", 2169*e1997b9aSAndroid Build Coastguard Worker params![caller_uid as i64, key.nspace], 2170*e1997b9aSAndroid Build Coastguard Worker |row| row.get(0), 2171*e1997b9aSAndroid Build Coastguard Worker ) 2172*e1997b9aSAndroid Build Coastguard Worker .optional() 2173*e1997b9aSAndroid Build Coastguard Worker .context("Domain::KEY_ID: query grant failed.")?; 2174*e1997b9aSAndroid Build Coastguard Worker access_vector.map(|p| p.into()) 2175*e1997b9aSAndroid Build Coastguard Worker } else { 2176*e1997b9aSAndroid Build Coastguard Worker None 2177*e1997b9aSAndroid Build Coastguard Worker }; 2178*e1997b9aSAndroid Build Coastguard Worker 2179*e1997b9aSAndroid Build Coastguard Worker let key_id = key.nspace; 2180*e1997b9aSAndroid Build Coastguard Worker let mut access_key: KeyDescriptor = key.clone(); 2181*e1997b9aSAndroid Build Coastguard Worker access_key.domain = domain; 2182*e1997b9aSAndroid Build Coastguard Worker access_key.nspace = namespace; 2183*e1997b9aSAndroid Build Coastguard Worker 2184*e1997b9aSAndroid Build Coastguard Worker Ok(KeyAccessInfo { key_id, descriptor: access_key, vector: access_vector }) 2185*e1997b9aSAndroid Build Coastguard Worker } 2186*e1997b9aSAndroid Build Coastguard Worker _ => Err(anyhow!(KsError::Rc(ResponseCode::INVALID_ARGUMENT))), 2187*e1997b9aSAndroid Build Coastguard Worker } 2188*e1997b9aSAndroid Build Coastguard Worker } 2189*e1997b9aSAndroid Build Coastguard Worker load_blob_components( key_id: i64, load_bits: KeyEntryLoadBits, tx: &Transaction, ) -> Result<(bool, Option<(Vec<u8>, BlobMetaData)>, Option<Vec<u8>>, Option<Vec<u8>>)>2190*e1997b9aSAndroid Build Coastguard Worker fn load_blob_components( 2191*e1997b9aSAndroid Build Coastguard Worker key_id: i64, 2192*e1997b9aSAndroid Build Coastguard Worker load_bits: KeyEntryLoadBits, 2193*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 2194*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(bool, Option<(Vec<u8>, BlobMetaData)>, Option<Vec<u8>>, Option<Vec<u8>>)> { 2195*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2196*e1997b9aSAndroid Build Coastguard Worker .prepare( 2197*e1997b9aSAndroid Build Coastguard Worker "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry 2198*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ? GROUP BY subcomponent_type;", 2199*e1997b9aSAndroid Build Coastguard Worker ) 2200*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("prepare statement failed."))?; 2201*e1997b9aSAndroid Build Coastguard Worker 2202*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt.query(params![key_id]).context(ks_err!("query failed."))?; 2203*e1997b9aSAndroid Build Coastguard Worker 2204*e1997b9aSAndroid Build Coastguard Worker let mut key_blob: Option<(i64, Vec<u8>)> = None; 2205*e1997b9aSAndroid Build Coastguard Worker let mut cert_blob: Option<Vec<u8>> = None; 2206*e1997b9aSAndroid Build Coastguard Worker let mut cert_chain_blob: Option<Vec<u8>> = None; 2207*e1997b9aSAndroid Build Coastguard Worker let mut has_km_blob: bool = false; 2208*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 2209*e1997b9aSAndroid Build Coastguard Worker let sub_type: SubComponentType = 2210*e1997b9aSAndroid Build Coastguard Worker row.get(1).context("Failed to extract subcomponent_type.")?; 2211*e1997b9aSAndroid Build Coastguard Worker has_km_blob = has_km_blob || sub_type == SubComponentType::KEY_BLOB; 2212*e1997b9aSAndroid Build Coastguard Worker match (sub_type, load_bits.load_public(), load_bits.load_km()) { 2213*e1997b9aSAndroid Build Coastguard Worker (SubComponentType::KEY_BLOB, _, true) => { 2214*e1997b9aSAndroid Build Coastguard Worker key_blob = Some(( 2215*e1997b9aSAndroid Build Coastguard Worker row.get(0).context("Failed to extract key blob id.")?, 2216*e1997b9aSAndroid Build Coastguard Worker row.get(2).context("Failed to extract key blob.")?, 2217*e1997b9aSAndroid Build Coastguard Worker )); 2218*e1997b9aSAndroid Build Coastguard Worker } 2219*e1997b9aSAndroid Build Coastguard Worker (SubComponentType::CERT, true, _) => { 2220*e1997b9aSAndroid Build Coastguard Worker cert_blob = 2221*e1997b9aSAndroid Build Coastguard Worker Some(row.get(2).context("Failed to extract public certificate blob.")?); 2222*e1997b9aSAndroid Build Coastguard Worker } 2223*e1997b9aSAndroid Build Coastguard Worker (SubComponentType::CERT_CHAIN, true, _) => { 2224*e1997b9aSAndroid Build Coastguard Worker cert_chain_blob = 2225*e1997b9aSAndroid Build Coastguard Worker Some(row.get(2).context("Failed to extract certificate chain blob.")?); 2226*e1997b9aSAndroid Build Coastguard Worker } 2227*e1997b9aSAndroid Build Coastguard Worker (SubComponentType::CERT, _, _) 2228*e1997b9aSAndroid Build Coastguard Worker | (SubComponentType::CERT_CHAIN, _, _) 2229*e1997b9aSAndroid Build Coastguard Worker | (SubComponentType::KEY_BLOB, _, _) => {} 2230*e1997b9aSAndroid Build Coastguard Worker _ => Err(KsError::sys()).context("Unknown subcomponent type.")?, 2231*e1997b9aSAndroid Build Coastguard Worker } 2232*e1997b9aSAndroid Build Coastguard Worker Ok(()) 2233*e1997b9aSAndroid Build Coastguard Worker }) 2234*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())?; 2235*e1997b9aSAndroid Build Coastguard Worker 2236*e1997b9aSAndroid Build Coastguard Worker let blob_info = key_blob.map_or::<Result<_>, _>(Ok(None), |(blob_id, blob)| { 2237*e1997b9aSAndroid Build Coastguard Worker Ok(Some(( 2238*e1997b9aSAndroid Build Coastguard Worker blob, 2239*e1997b9aSAndroid Build Coastguard Worker BlobMetaData::load_from_db(blob_id, tx) 2240*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Trying to load blob_metadata."))?, 2241*e1997b9aSAndroid Build Coastguard Worker ))) 2242*e1997b9aSAndroid Build Coastguard Worker })?; 2243*e1997b9aSAndroid Build Coastguard Worker 2244*e1997b9aSAndroid Build Coastguard Worker Ok((has_km_blob, blob_info, cert_blob, cert_chain_blob)) 2245*e1997b9aSAndroid Build Coastguard Worker } 2246*e1997b9aSAndroid Build Coastguard Worker load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>>2247*e1997b9aSAndroid Build Coastguard Worker fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> { 2248*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2249*e1997b9aSAndroid Build Coastguard Worker .prepare( 2250*e1997b9aSAndroid Build Coastguard Worker "SELECT tag, data, security_level from persistent.keyparameter 2251*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ?;", 2252*e1997b9aSAndroid Build Coastguard Worker ) 2253*e1997b9aSAndroid Build Coastguard Worker .context("In load_key_parameters: prepare statement failed.")?; 2254*e1997b9aSAndroid Build Coastguard Worker 2255*e1997b9aSAndroid Build Coastguard Worker let mut parameters: Vec<KeyParameter> = Vec::new(); 2256*e1997b9aSAndroid Build Coastguard Worker 2257*e1997b9aSAndroid Build Coastguard Worker let mut rows = 2258*e1997b9aSAndroid Build Coastguard Worker stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?; 2259*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 2260*e1997b9aSAndroid Build Coastguard Worker let tag = Tag(row.get(0).context("Failed to read tag.")?); 2261*e1997b9aSAndroid Build Coastguard Worker let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?); 2262*e1997b9aSAndroid Build Coastguard Worker parameters.push( 2263*e1997b9aSAndroid Build Coastguard Worker KeyParameter::new_from_sql(tag, &SqlField::new(1, row), sec_level) 2264*e1997b9aSAndroid Build Coastguard Worker .context("Failed to read KeyParameter.")?, 2265*e1997b9aSAndroid Build Coastguard Worker ); 2266*e1997b9aSAndroid Build Coastguard Worker Ok(()) 2267*e1997b9aSAndroid Build Coastguard Worker }) 2268*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())?; 2269*e1997b9aSAndroid Build Coastguard Worker 2270*e1997b9aSAndroid Build Coastguard Worker Ok(parameters) 2271*e1997b9aSAndroid Build Coastguard Worker } 2272*e1997b9aSAndroid Build Coastguard Worker 2273*e1997b9aSAndroid Build Coastguard Worker /// Decrements the usage count of a limited use key. This function first checks whether the 2274*e1997b9aSAndroid Build Coastguard Worker /// usage has been exhausted, if not, decreases the usage count. If the usage count reaches 2275*e1997b9aSAndroid Build Coastguard Worker /// zero, the key also gets marked unreferenced and scheduled for deletion. 2276*e1997b9aSAndroid Build Coastguard Worker /// 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<()>2277*e1997b9aSAndroid Build Coastguard Worker pub fn check_and_update_key_usage_count(&mut self, key_id: i64) -> Result<()> { 2278*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::check_and_update_key_usage_count"); 2279*e1997b9aSAndroid Build Coastguard Worker 2280*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_check_and_update_key_usage_count"), |tx| { 2281*e1997b9aSAndroid Build Coastguard Worker let limit: Option<i32> = tx 2282*e1997b9aSAndroid Build Coastguard Worker .query_row( 2283*e1997b9aSAndroid Build Coastguard Worker "SELECT data FROM persistent.keyparameter WHERE keyentryid = ? AND tag = ?;", 2284*e1997b9aSAndroid Build Coastguard Worker params![key_id, Tag::USAGE_COUNT_LIMIT.0], 2285*e1997b9aSAndroid Build Coastguard Worker |row| row.get(0), 2286*e1997b9aSAndroid Build Coastguard Worker ) 2287*e1997b9aSAndroid Build Coastguard Worker .optional() 2288*e1997b9aSAndroid Build Coastguard Worker .context("Trying to load usage count")?; 2289*e1997b9aSAndroid Build Coastguard Worker 2290*e1997b9aSAndroid Build Coastguard Worker let limit = limit 2291*e1997b9aSAndroid Build Coastguard Worker .ok_or(KsError::Km(ErrorCode::INVALID_KEY_BLOB)) 2292*e1997b9aSAndroid Build Coastguard Worker .context("The Key no longer exists. Key is exhausted.")?; 2293*e1997b9aSAndroid Build Coastguard Worker 2294*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2295*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.keyparameter 2296*e1997b9aSAndroid Build Coastguard Worker SET data = data - 1 2297*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ? AND tag = ? AND data > 0;", 2298*e1997b9aSAndroid Build Coastguard Worker params![key_id, Tag::USAGE_COUNT_LIMIT.0], 2299*e1997b9aSAndroid Build Coastguard Worker ) 2300*e1997b9aSAndroid Build Coastguard Worker .context("Failed to update key usage count.")?; 2301*e1997b9aSAndroid Build Coastguard Worker 2302*e1997b9aSAndroid Build Coastguard Worker match limit { 2303*e1997b9aSAndroid Build Coastguard Worker 1 => Self::mark_unreferenced(tx, key_id) 2304*e1997b9aSAndroid Build Coastguard Worker .map(|need_gc| (need_gc, ())) 2305*e1997b9aSAndroid Build Coastguard Worker .context("Trying to mark limited use key for deletion."), 2306*e1997b9aSAndroid Build Coastguard Worker 0 => Err(KsError::Km(ErrorCode::INVALID_KEY_BLOB)).context("Key is exhausted."), 2307*e1997b9aSAndroid Build Coastguard Worker _ => Ok(()).no_gc(), 2308*e1997b9aSAndroid Build Coastguard Worker } 2309*e1997b9aSAndroid Build Coastguard Worker }) 2310*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2311*e1997b9aSAndroid Build Coastguard Worker } 2312*e1997b9aSAndroid Build Coastguard Worker 2313*e1997b9aSAndroid Build Coastguard Worker /// Load a key entry by the given key descriptor. 2314*e1997b9aSAndroid Build Coastguard Worker /// It uses the `check_permission` callback to verify if the access is allowed 2315*e1997b9aSAndroid Build Coastguard Worker /// given the key access tuple read from the database using `load_access_tuple`. 2316*e1997b9aSAndroid Build Coastguard Worker /// With `load_bits` the caller may specify which blobs shall be loaded from 2317*e1997b9aSAndroid Build Coastguard Worker /// 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)>2318*e1997b9aSAndroid Build Coastguard Worker pub fn load_key_entry( 2319*e1997b9aSAndroid Build Coastguard Worker &mut self, 2320*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 2321*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 2322*e1997b9aSAndroid Build Coastguard Worker load_bits: KeyEntryLoadBits, 2323*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 2324*e1997b9aSAndroid Build Coastguard Worker check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, 2325*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(KeyIdGuard, KeyEntry)> { 2326*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::load_key_entry"); 2327*e1997b9aSAndroid Build Coastguard Worker 2328*e1997b9aSAndroid Build Coastguard Worker loop { 2329*e1997b9aSAndroid Build Coastguard Worker match self.load_key_entry_internal( 2330*e1997b9aSAndroid Build Coastguard Worker key, 2331*e1997b9aSAndroid Build Coastguard Worker key_type, 2332*e1997b9aSAndroid Build Coastguard Worker load_bits, 2333*e1997b9aSAndroid Build Coastguard Worker caller_uid, 2334*e1997b9aSAndroid Build Coastguard Worker &check_permission, 2335*e1997b9aSAndroid Build Coastguard Worker ) { 2336*e1997b9aSAndroid Build Coastguard Worker Ok(result) => break Ok(result), 2337*e1997b9aSAndroid Build Coastguard Worker Err(e) => { 2338*e1997b9aSAndroid Build Coastguard Worker if Self::is_locked_error(&e) { 2339*e1997b9aSAndroid Build Coastguard Worker std::thread::sleep(DB_BUSY_RETRY_INTERVAL); 2340*e1997b9aSAndroid Build Coastguard Worker continue; 2341*e1997b9aSAndroid Build Coastguard Worker } else { 2342*e1997b9aSAndroid Build Coastguard Worker return Err(e).context(ks_err!()); 2343*e1997b9aSAndroid Build Coastguard Worker } 2344*e1997b9aSAndroid Build Coastguard Worker } 2345*e1997b9aSAndroid Build Coastguard Worker } 2346*e1997b9aSAndroid Build Coastguard Worker } 2347*e1997b9aSAndroid Build Coastguard Worker } 2348*e1997b9aSAndroid Build Coastguard Worker 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)>2349*e1997b9aSAndroid Build Coastguard Worker fn load_key_entry_internal( 2350*e1997b9aSAndroid Build Coastguard Worker &mut self, 2351*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 2352*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 2353*e1997b9aSAndroid Build Coastguard Worker load_bits: KeyEntryLoadBits, 2354*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 2355*e1997b9aSAndroid Build Coastguard Worker check_permission: &impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, 2356*e1997b9aSAndroid Build Coastguard Worker ) -> Result<(KeyIdGuard, KeyEntry)> { 2357*e1997b9aSAndroid Build Coastguard Worker // KEY ID LOCK 1/2 2358*e1997b9aSAndroid Build Coastguard Worker // If we got a key descriptor with a key id we can get the lock right away. 2359*e1997b9aSAndroid Build Coastguard Worker // Otherwise we have to defer it until we know the key id. 2360*e1997b9aSAndroid Build Coastguard Worker let key_id_guard = match key.domain { 2361*e1997b9aSAndroid Build Coastguard Worker Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)), 2362*e1997b9aSAndroid Build Coastguard Worker _ => None, 2363*e1997b9aSAndroid Build Coastguard Worker }; 2364*e1997b9aSAndroid Build Coastguard Worker 2365*e1997b9aSAndroid Build Coastguard Worker let tx = self 2366*e1997b9aSAndroid Build Coastguard Worker .conn 2367*e1997b9aSAndroid Build Coastguard Worker .unchecked_transaction() 2368*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to initialize transaction."))?; 2369*e1997b9aSAndroid Build Coastguard Worker 2370*e1997b9aSAndroid Build Coastguard Worker // Load the key_id and complete the access control tuple. 2371*e1997b9aSAndroid Build Coastguard Worker let access = Self::load_access_tuple(&tx, key, key_type, caller_uid).context(ks_err!())?; 2372*e1997b9aSAndroid Build Coastguard Worker 2373*e1997b9aSAndroid Build Coastguard Worker // Perform access control. It is vital that we return here if the permission is denied. 2374*e1997b9aSAndroid Build Coastguard Worker // So do not touch that '?' at the end. 2375*e1997b9aSAndroid Build Coastguard Worker check_permission(&access.descriptor, access.vector).context(ks_err!())?; 2376*e1997b9aSAndroid Build Coastguard Worker 2377*e1997b9aSAndroid Build Coastguard Worker // KEY ID LOCK 2/2 2378*e1997b9aSAndroid Build Coastguard Worker // If we did not get a key id lock by now, it was because we got a key descriptor 2379*e1997b9aSAndroid Build Coastguard Worker // without a key id. At this point we got the key id, so we can try and get a lock. 2380*e1997b9aSAndroid Build Coastguard Worker // However, we cannot block here, because we are in the middle of the transaction. 2381*e1997b9aSAndroid Build Coastguard Worker // So first we try to get the lock non blocking. If that fails, we roll back the 2382*e1997b9aSAndroid Build Coastguard Worker // transaction and block until we get the lock. After we successfully got the lock, 2383*e1997b9aSAndroid Build Coastguard Worker // we start a new transaction and load the access tuple again. 2384*e1997b9aSAndroid Build Coastguard Worker // 2385*e1997b9aSAndroid Build Coastguard Worker // We don't need to perform access control again, because we already established 2386*e1997b9aSAndroid Build Coastguard Worker // that the caller had access to the given key. But we need to make sure that the 2387*e1997b9aSAndroid Build Coastguard Worker // key id still exists. So we have to load the key entry by key id this time. 2388*e1997b9aSAndroid Build Coastguard Worker let (key_id_guard, tx) = match key_id_guard { 2389*e1997b9aSAndroid Build Coastguard Worker None => match KEY_ID_LOCK.try_get(access.key_id) { 2390*e1997b9aSAndroid Build Coastguard Worker None => { 2391*e1997b9aSAndroid Build Coastguard Worker // Roll back the transaction. 2392*e1997b9aSAndroid Build Coastguard Worker tx.rollback().context(ks_err!("Failed to roll back transaction."))?; 2393*e1997b9aSAndroid Build Coastguard Worker 2394*e1997b9aSAndroid Build Coastguard Worker // Block until we have a key id lock. 2395*e1997b9aSAndroid Build Coastguard Worker let key_id_guard = KEY_ID_LOCK.get(access.key_id); 2396*e1997b9aSAndroid Build Coastguard Worker 2397*e1997b9aSAndroid Build Coastguard Worker // Create a new transaction. 2398*e1997b9aSAndroid Build Coastguard Worker let tx = self 2399*e1997b9aSAndroid Build Coastguard Worker .conn 2400*e1997b9aSAndroid Build Coastguard Worker .unchecked_transaction() 2401*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to initialize transaction."))?; 2402*e1997b9aSAndroid Build Coastguard Worker 2403*e1997b9aSAndroid Build Coastguard Worker Self::load_access_tuple( 2404*e1997b9aSAndroid Build Coastguard Worker &tx, 2405*e1997b9aSAndroid Build Coastguard Worker // This time we have to load the key by the retrieved key id, because the 2406*e1997b9aSAndroid Build Coastguard Worker // alias may have been rebound after we rolled back the transaction. 2407*e1997b9aSAndroid Build Coastguard Worker &KeyDescriptor { 2408*e1997b9aSAndroid Build Coastguard Worker domain: Domain::KEY_ID, 2409*e1997b9aSAndroid Build Coastguard Worker nspace: access.key_id, 2410*e1997b9aSAndroid Build Coastguard Worker ..Default::default() 2411*e1997b9aSAndroid Build Coastguard Worker }, 2412*e1997b9aSAndroid Build Coastguard Worker key_type, 2413*e1997b9aSAndroid Build Coastguard Worker caller_uid, 2414*e1997b9aSAndroid Build Coastguard Worker ) 2415*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("(deferred key lock)"))?; 2416*e1997b9aSAndroid Build Coastguard Worker (key_id_guard, tx) 2417*e1997b9aSAndroid Build Coastguard Worker } 2418*e1997b9aSAndroid Build Coastguard Worker Some(l) => (l, tx), 2419*e1997b9aSAndroid Build Coastguard Worker }, 2420*e1997b9aSAndroid Build Coastguard Worker Some(key_id_guard) => (key_id_guard, tx), 2421*e1997b9aSAndroid Build Coastguard Worker }; 2422*e1997b9aSAndroid Build Coastguard Worker 2423*e1997b9aSAndroid Build Coastguard Worker let key_entry = 2424*e1997b9aSAndroid Build Coastguard Worker Self::load_key_components(&tx, load_bits, key_id_guard.id()).context(ks_err!())?; 2425*e1997b9aSAndroid Build Coastguard Worker 2426*e1997b9aSAndroid Build Coastguard Worker tx.commit().context(ks_err!("Failed to commit transaction."))?; 2427*e1997b9aSAndroid Build Coastguard Worker 2428*e1997b9aSAndroid Build Coastguard Worker Ok((key_id_guard, key_entry)) 2429*e1997b9aSAndroid Build Coastguard Worker } 2430*e1997b9aSAndroid Build Coastguard Worker mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<bool>2431*e1997b9aSAndroid Build Coastguard Worker fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<bool> { 2432*e1997b9aSAndroid Build Coastguard Worker let updated = tx 2433*e1997b9aSAndroid Build Coastguard Worker .execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id]) 2434*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keyentry.")?; 2435*e1997b9aSAndroid Build Coastguard Worker tx.execute("DELETE FROM persistent.keymetadata WHERE keyentryid = ?;", params![key_id]) 2436*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keymetadata.")?; 2437*e1997b9aSAndroid Build Coastguard Worker tx.execute("DELETE FROM persistent.keyparameter WHERE keyentryid = ?;", params![key_id]) 2438*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keyparameters.")?; 2439*e1997b9aSAndroid Build Coastguard Worker tx.execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id]) 2440*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete grants.")?; 2441*e1997b9aSAndroid Build Coastguard Worker // The associated blobentry rows are not immediately deleted when the owning keyentry is 2442*e1997b9aSAndroid Build Coastguard Worker // removed, because a KeyMint `deleteKey()` invocation is needed (specifically for the 2443*e1997b9aSAndroid Build Coastguard Worker // `KEY_BLOB`). Mark the affected rows with `state=Orphaned` so a subsequent garbage 2444*e1997b9aSAndroid Build Coastguard Worker // collection can do this. 2445*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2446*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.blobentry SET state = ? WHERE keyentryid = ?", 2447*e1997b9aSAndroid Build Coastguard Worker params![BlobState::Orphaned, key_id], 2448*e1997b9aSAndroid Build Coastguard Worker ) 2449*e1997b9aSAndroid Build Coastguard Worker .context("Trying to mark blobentrys as superseded")?; 2450*e1997b9aSAndroid Build Coastguard Worker Ok(updated != 0) 2451*e1997b9aSAndroid Build Coastguard Worker } 2452*e1997b9aSAndroid Build Coastguard Worker 2453*e1997b9aSAndroid Build Coastguard Worker /// Marks the given key as unreferenced and removes all of the grants to this key. 2454*e1997b9aSAndroid Build Coastguard Worker /// 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<()>2455*e1997b9aSAndroid Build Coastguard Worker pub fn unbind_key( 2456*e1997b9aSAndroid Build Coastguard Worker &mut self, 2457*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 2458*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 2459*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 2460*e1997b9aSAndroid Build Coastguard Worker check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>, 2461*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> { 2462*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::unbind_key"); 2463*e1997b9aSAndroid Build Coastguard Worker 2464*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_unbind_key"), |tx| { 2465*e1997b9aSAndroid Build Coastguard Worker let access = Self::load_access_tuple(tx, key, key_type, caller_uid) 2466*e1997b9aSAndroid Build Coastguard Worker .context("Trying to get access tuple.")?; 2467*e1997b9aSAndroid Build Coastguard Worker 2468*e1997b9aSAndroid Build Coastguard Worker // Perform access control. It is vital that we return here if the permission is denied. 2469*e1997b9aSAndroid Build Coastguard Worker // So do not touch that '?' at the end. 2470*e1997b9aSAndroid Build Coastguard Worker check_permission(&access.descriptor, access.vector) 2471*e1997b9aSAndroid Build Coastguard Worker .context("While checking permission.")?; 2472*e1997b9aSAndroid Build Coastguard Worker 2473*e1997b9aSAndroid Build Coastguard Worker Self::mark_unreferenced(tx, access.key_id) 2474*e1997b9aSAndroid Build Coastguard Worker .map(|need_gc| (need_gc, ())) 2475*e1997b9aSAndroid Build Coastguard Worker .context("Trying to mark the key unreferenced.") 2476*e1997b9aSAndroid Build Coastguard Worker }) 2477*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2478*e1997b9aSAndroid Build Coastguard Worker } 2479*e1997b9aSAndroid Build Coastguard Worker get_key_km_uuid(tx: &Transaction, key_id: i64) -> Result<Uuid>2480*e1997b9aSAndroid Build Coastguard Worker fn get_key_km_uuid(tx: &Transaction, key_id: i64) -> Result<Uuid> { 2481*e1997b9aSAndroid Build Coastguard Worker tx.query_row( 2482*e1997b9aSAndroid Build Coastguard Worker "SELECT km_uuid FROM persistent.keyentry WHERE id = ?", 2483*e1997b9aSAndroid Build Coastguard Worker params![key_id], 2484*e1997b9aSAndroid Build Coastguard Worker |row| row.get(0), 2485*e1997b9aSAndroid Build Coastguard Worker ) 2486*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2487*e1997b9aSAndroid Build Coastguard Worker } 2488*e1997b9aSAndroid Build Coastguard Worker 2489*e1997b9aSAndroid Build Coastguard Worker /// Delete all artifacts belonging to the namespace given by the domain-namespace tuple. 2490*e1997b9aSAndroid Build Coastguard Worker /// This leaves all of the blob entries orphaned for subsequent garbage collection. unbind_keys_for_namespace(&mut self, domain: Domain, namespace: i64) -> Result<()>2491*e1997b9aSAndroid Build Coastguard Worker pub fn unbind_keys_for_namespace(&mut self, domain: Domain, namespace: i64) -> Result<()> { 2492*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::unbind_keys_for_namespace"); 2493*e1997b9aSAndroid Build Coastguard Worker 2494*e1997b9aSAndroid Build Coastguard Worker if !(domain == Domain::APP || domain == Domain::SELINUX) { 2495*e1997b9aSAndroid Build Coastguard Worker return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)).context(ks_err!()); 2496*e1997b9aSAndroid Build Coastguard Worker } 2497*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_unbind_keys_for_namespace"), |tx| { 2498*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2499*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.keymetadata 2500*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid IN ( 2501*e1997b9aSAndroid Build Coastguard Worker SELECT id FROM persistent.keyentry 2502*e1997b9aSAndroid Build Coastguard Worker WHERE domain = ? AND namespace = ? AND key_type = ? 2503*e1997b9aSAndroid Build Coastguard Worker );", 2504*e1997b9aSAndroid Build Coastguard Worker params![domain.0, namespace, KeyType::Client], 2505*e1997b9aSAndroid Build Coastguard Worker ) 2506*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keymetadata.")?; 2507*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2508*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.keyparameter 2509*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid IN ( 2510*e1997b9aSAndroid Build Coastguard Worker SELECT id FROM persistent.keyentry 2511*e1997b9aSAndroid Build Coastguard Worker WHERE domain = ? AND namespace = ? AND key_type = ? 2512*e1997b9aSAndroid Build Coastguard Worker );", 2513*e1997b9aSAndroid Build Coastguard Worker params![domain.0, namespace, KeyType::Client], 2514*e1997b9aSAndroid Build Coastguard Worker ) 2515*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keyparameters.")?; 2516*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2517*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.grant 2518*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid IN ( 2519*e1997b9aSAndroid Build Coastguard Worker SELECT id FROM persistent.keyentry 2520*e1997b9aSAndroid Build Coastguard Worker WHERE domain = ? AND namespace = ? AND key_type = ? 2521*e1997b9aSAndroid Build Coastguard Worker );", 2522*e1997b9aSAndroid Build Coastguard Worker params![domain.0, namespace, KeyType::Client], 2523*e1997b9aSAndroid Build Coastguard Worker ) 2524*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete grants.")?; 2525*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2526*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.keyentry 2527*e1997b9aSAndroid Build Coastguard Worker WHERE domain = ? AND namespace = ? AND key_type = ?;", 2528*e1997b9aSAndroid Build Coastguard Worker params![domain.0, namespace, KeyType::Client], 2529*e1997b9aSAndroid Build Coastguard Worker ) 2530*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keyentry.")?; 2531*e1997b9aSAndroid Build Coastguard Worker Ok(()).need_gc() 2532*e1997b9aSAndroid Build Coastguard Worker }) 2533*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2534*e1997b9aSAndroid Build Coastguard Worker } 2535*e1997b9aSAndroid Build Coastguard Worker cleanup_unreferenced(tx: &Transaction) -> Result<()>2536*e1997b9aSAndroid Build Coastguard Worker fn cleanup_unreferenced(tx: &Transaction) -> Result<()> { 2537*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::cleanup_unreferenced"); 2538*e1997b9aSAndroid Build Coastguard Worker { 2539*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2540*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.keymetadata 2541*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid IN ( 2542*e1997b9aSAndroid Build Coastguard Worker SELECT id FROM persistent.keyentry 2543*e1997b9aSAndroid Build Coastguard Worker WHERE state = ? 2544*e1997b9aSAndroid Build Coastguard Worker );", 2545*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced], 2546*e1997b9aSAndroid Build Coastguard Worker ) 2547*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keymetadata.")?; 2548*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2549*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.keyparameter 2550*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid IN ( 2551*e1997b9aSAndroid Build Coastguard Worker SELECT id FROM persistent.keyentry 2552*e1997b9aSAndroid Build Coastguard Worker WHERE state = ? 2553*e1997b9aSAndroid Build Coastguard Worker );", 2554*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced], 2555*e1997b9aSAndroid Build Coastguard Worker ) 2556*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keyparameters.")?; 2557*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2558*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.grant 2559*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid IN ( 2560*e1997b9aSAndroid Build Coastguard Worker SELECT id FROM persistent.keyentry 2561*e1997b9aSAndroid Build Coastguard Worker WHERE state = ? 2562*e1997b9aSAndroid Build Coastguard Worker );", 2563*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced], 2564*e1997b9aSAndroid Build Coastguard Worker ) 2565*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete grants.")?; 2566*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2567*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.keyentry 2568*e1997b9aSAndroid Build Coastguard Worker WHERE state = ?;", 2569*e1997b9aSAndroid Build Coastguard Worker params![KeyLifeCycle::Unreferenced], 2570*e1997b9aSAndroid Build Coastguard Worker ) 2571*e1997b9aSAndroid Build Coastguard Worker .context("Trying to delete keyentry.")?; 2572*e1997b9aSAndroid Build Coastguard Worker Result::<()>::Ok(()) 2573*e1997b9aSAndroid Build Coastguard Worker } 2574*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2575*e1997b9aSAndroid Build Coastguard Worker } 2576*e1997b9aSAndroid Build Coastguard Worker 2577*e1997b9aSAndroid Build Coastguard Worker /// Deletes all keys for the given user, including both client keys and super keys. unbind_keys_for_user(&mut self, user_id: u32) -> Result<()>2578*e1997b9aSAndroid Build Coastguard Worker pub fn unbind_keys_for_user(&mut self, user_id: u32) -> Result<()> { 2579*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::unbind_keys_for_user"); 2580*e1997b9aSAndroid Build Coastguard Worker 2581*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_unbind_keys_for_user"), |tx| { 2582*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2583*e1997b9aSAndroid Build Coastguard Worker .prepare(&format!( 2584*e1997b9aSAndroid Build Coastguard Worker "SELECT id from persistent.keyentry 2585*e1997b9aSAndroid Build Coastguard Worker WHERE ( 2586*e1997b9aSAndroid Build Coastguard Worker key_type = ? 2587*e1997b9aSAndroid Build Coastguard Worker AND domain = ? 2588*e1997b9aSAndroid Build Coastguard Worker AND cast ( (namespace/{aid_user_offset}) as int) = ? 2589*e1997b9aSAndroid Build Coastguard Worker AND state = ? 2590*e1997b9aSAndroid Build Coastguard Worker ) OR ( 2591*e1997b9aSAndroid Build Coastguard Worker key_type = ? 2592*e1997b9aSAndroid Build Coastguard Worker AND namespace = ? 2593*e1997b9aSAndroid Build Coastguard Worker AND state = ? 2594*e1997b9aSAndroid Build Coastguard Worker );", 2595*e1997b9aSAndroid Build Coastguard Worker aid_user_offset = AID_USER_OFFSET 2596*e1997b9aSAndroid Build Coastguard Worker )) 2597*e1997b9aSAndroid Build Coastguard Worker .context(concat!( 2598*e1997b9aSAndroid Build Coastguard Worker "In unbind_keys_for_user. ", 2599*e1997b9aSAndroid Build Coastguard Worker "Failed to prepare the query to find the keys created by apps." 2600*e1997b9aSAndroid Build Coastguard Worker ))?; 2601*e1997b9aSAndroid Build Coastguard Worker 2602*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 2603*e1997b9aSAndroid Build Coastguard Worker .query(params![ 2604*e1997b9aSAndroid Build Coastguard Worker // WHERE client key: 2605*e1997b9aSAndroid Build Coastguard Worker KeyType::Client, 2606*e1997b9aSAndroid Build Coastguard Worker Domain::APP.0 as u32, 2607*e1997b9aSAndroid Build Coastguard Worker user_id, 2608*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Live, 2609*e1997b9aSAndroid Build Coastguard Worker // OR super key: 2610*e1997b9aSAndroid Build Coastguard Worker KeyType::Super, 2611*e1997b9aSAndroid Build Coastguard Worker user_id, 2612*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Live 2613*e1997b9aSAndroid Build Coastguard Worker ]) 2614*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to query the keys created by apps."))?; 2615*e1997b9aSAndroid Build Coastguard Worker 2616*e1997b9aSAndroid Build Coastguard Worker let mut key_ids: Vec<i64> = Vec::new(); 2617*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 2618*e1997b9aSAndroid Build Coastguard Worker key_ids 2619*e1997b9aSAndroid Build Coastguard Worker .push(row.get(0).context("Failed to read key id of a key created by an app.")?); 2620*e1997b9aSAndroid Build Coastguard Worker Ok(()) 2621*e1997b9aSAndroid Build Coastguard Worker }) 2622*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())?; 2623*e1997b9aSAndroid Build Coastguard Worker 2624*e1997b9aSAndroid Build Coastguard Worker let mut notify_gc = false; 2625*e1997b9aSAndroid Build Coastguard Worker for key_id in key_ids { 2626*e1997b9aSAndroid Build Coastguard Worker notify_gc = Self::mark_unreferenced(tx, key_id) 2627*e1997b9aSAndroid Build Coastguard Worker .context("In unbind_keys_for_user.")? 2628*e1997b9aSAndroid Build Coastguard Worker || notify_gc; 2629*e1997b9aSAndroid Build Coastguard Worker } 2630*e1997b9aSAndroid Build Coastguard Worker Ok(()).do_gc(notify_gc) 2631*e1997b9aSAndroid Build Coastguard Worker }) 2632*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2633*e1997b9aSAndroid Build Coastguard Worker } 2634*e1997b9aSAndroid Build Coastguard Worker 2635*e1997b9aSAndroid Build Coastguard Worker /// Deletes all auth-bound keys, i.e. keys that require user authentication, for the given user. 2636*e1997b9aSAndroid Build Coastguard Worker /// This runs when the user's lock screen is being changed to Swipe or None. 2637*e1997b9aSAndroid Build Coastguard Worker /// 2638*e1997b9aSAndroid Build Coastguard Worker /// This intentionally does *not* delete keys that require that the device be unlocked, unless 2639*e1997b9aSAndroid Build Coastguard Worker /// such keys also require user authentication. Keystore's concept of user authentication is 2640*e1997b9aSAndroid Build Coastguard Worker /// fairly strong, and it requires that keys that require authentication be deleted as soon as 2641*e1997b9aSAndroid Build Coastguard Worker /// authentication is no longer possible. In contrast, keys that just require that the device 2642*e1997b9aSAndroid Build Coastguard Worker /// be unlocked should remain usable when the lock screen is set to Swipe or None, as the device 2643*e1997b9aSAndroid Build Coastguard Worker /// is always considered "unlocked" in that case. unbind_auth_bound_keys_for_user(&mut self, user_id: u32) -> Result<()>2644*e1997b9aSAndroid Build Coastguard Worker pub fn unbind_auth_bound_keys_for_user(&mut self, user_id: u32) -> Result<()> { 2645*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::unbind_auth_bound_keys_for_user"); 2646*e1997b9aSAndroid Build Coastguard Worker 2647*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_unbind_auth_bound_keys_for_user"), |tx| { 2648*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2649*e1997b9aSAndroid Build Coastguard Worker .prepare(&format!( 2650*e1997b9aSAndroid Build Coastguard Worker "SELECT id from persistent.keyentry 2651*e1997b9aSAndroid Build Coastguard Worker WHERE key_type = ? 2652*e1997b9aSAndroid Build Coastguard Worker AND domain = ? 2653*e1997b9aSAndroid Build Coastguard Worker AND cast ( (namespace/{aid_user_offset}) as int) = ? 2654*e1997b9aSAndroid Build Coastguard Worker AND state = ?;", 2655*e1997b9aSAndroid Build Coastguard Worker aid_user_offset = AID_USER_OFFSET 2656*e1997b9aSAndroid Build Coastguard Worker )) 2657*e1997b9aSAndroid Build Coastguard Worker .context(concat!( 2658*e1997b9aSAndroid Build Coastguard Worker "In unbind_auth_bound_keys_for_user. ", 2659*e1997b9aSAndroid Build Coastguard Worker "Failed to prepare the query to find the keys created by apps." 2660*e1997b9aSAndroid Build Coastguard Worker ))?; 2661*e1997b9aSAndroid Build Coastguard Worker 2662*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 2663*e1997b9aSAndroid Build Coastguard Worker .query(params![KeyType::Client, Domain::APP.0 as u32, user_id, KeyLifeCycle::Live,]) 2664*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to query the keys created by apps."))?; 2665*e1997b9aSAndroid Build Coastguard Worker 2666*e1997b9aSAndroid Build Coastguard Worker let mut key_ids: Vec<i64> = Vec::new(); 2667*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 2668*e1997b9aSAndroid Build Coastguard Worker key_ids 2669*e1997b9aSAndroid Build Coastguard Worker .push(row.get(0).context("Failed to read key id of a key created by an app.")?); 2670*e1997b9aSAndroid Build Coastguard Worker Ok(()) 2671*e1997b9aSAndroid Build Coastguard Worker }) 2672*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())?; 2673*e1997b9aSAndroid Build Coastguard Worker 2674*e1997b9aSAndroid Build Coastguard Worker let mut notify_gc = false; 2675*e1997b9aSAndroid Build Coastguard Worker let mut num_unbound = 0; 2676*e1997b9aSAndroid Build Coastguard Worker for key_id in key_ids { 2677*e1997b9aSAndroid Build Coastguard Worker // Load the key parameters and filter out non-auth-bound keys. To identify 2678*e1997b9aSAndroid Build Coastguard Worker // auth-bound keys, use the presence of UserSecureID. The absence of NoAuthRequired 2679*e1997b9aSAndroid Build Coastguard Worker // could also be used, but UserSecureID is what Keystore treats as authoritative 2680*e1997b9aSAndroid Build Coastguard Worker // when actually enforcing the key parameters (it might not matter, though). 2681*e1997b9aSAndroid Build Coastguard Worker let params = Self::load_key_parameters(key_id, tx) 2682*e1997b9aSAndroid Build Coastguard Worker .context("Failed to load key parameters.")?; 2683*e1997b9aSAndroid Build Coastguard Worker let is_auth_bound_key = params.iter().any(|kp| { 2684*e1997b9aSAndroid Build Coastguard Worker matches!(kp.key_parameter_value(), KeyParameterValue::UserSecureID(_)) 2685*e1997b9aSAndroid Build Coastguard Worker }); 2686*e1997b9aSAndroid Build Coastguard Worker if is_auth_bound_key { 2687*e1997b9aSAndroid Build Coastguard Worker notify_gc = Self::mark_unreferenced(tx, key_id) 2688*e1997b9aSAndroid Build Coastguard Worker .context("In unbind_auth_bound_keys_for_user.")? 2689*e1997b9aSAndroid Build Coastguard Worker || notify_gc; 2690*e1997b9aSAndroid Build Coastguard Worker num_unbound += 1; 2691*e1997b9aSAndroid Build Coastguard Worker } 2692*e1997b9aSAndroid Build Coastguard Worker } 2693*e1997b9aSAndroid Build Coastguard Worker log::info!("Deleting {num_unbound} auth-bound keys for user {user_id}"); 2694*e1997b9aSAndroid Build Coastguard Worker Ok(()).do_gc(notify_gc) 2695*e1997b9aSAndroid Build Coastguard Worker }) 2696*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2697*e1997b9aSAndroid Build Coastguard Worker } 2698*e1997b9aSAndroid Build Coastguard Worker load_key_components( tx: &Transaction, load_bits: KeyEntryLoadBits, key_id: i64, ) -> Result<KeyEntry>2699*e1997b9aSAndroid Build Coastguard Worker fn load_key_components( 2700*e1997b9aSAndroid Build Coastguard Worker tx: &Transaction, 2701*e1997b9aSAndroid Build Coastguard Worker load_bits: KeyEntryLoadBits, 2702*e1997b9aSAndroid Build Coastguard Worker key_id: i64, 2703*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyEntry> { 2704*e1997b9aSAndroid Build Coastguard Worker let metadata = KeyMetaData::load_from_db(key_id, tx).context("In load_key_components.")?; 2705*e1997b9aSAndroid Build Coastguard Worker 2706*e1997b9aSAndroid Build Coastguard Worker let (has_km_blob, key_blob_info, cert_blob, cert_chain_blob) = 2707*e1997b9aSAndroid Build Coastguard Worker Self::load_blob_components(key_id, load_bits, tx).context("In load_key_components.")?; 2708*e1997b9aSAndroid Build Coastguard Worker 2709*e1997b9aSAndroid Build Coastguard Worker let parameters = Self::load_key_parameters(key_id, tx) 2710*e1997b9aSAndroid Build Coastguard Worker .context("In load_key_components: Trying to load key parameters.")?; 2711*e1997b9aSAndroid Build Coastguard Worker 2712*e1997b9aSAndroid Build Coastguard Worker let km_uuid = Self::get_key_km_uuid(tx, key_id) 2713*e1997b9aSAndroid Build Coastguard Worker .context("In load_key_components: Trying to get KM uuid.")?; 2714*e1997b9aSAndroid Build Coastguard Worker 2715*e1997b9aSAndroid Build Coastguard Worker Ok(KeyEntry { 2716*e1997b9aSAndroid Build Coastguard Worker id: key_id, 2717*e1997b9aSAndroid Build Coastguard Worker key_blob_info, 2718*e1997b9aSAndroid Build Coastguard Worker cert: cert_blob, 2719*e1997b9aSAndroid Build Coastguard Worker cert_chain: cert_chain_blob, 2720*e1997b9aSAndroid Build Coastguard Worker km_uuid, 2721*e1997b9aSAndroid Build Coastguard Worker parameters, 2722*e1997b9aSAndroid Build Coastguard Worker metadata, 2723*e1997b9aSAndroid Build Coastguard Worker pure_cert: !has_km_blob, 2724*e1997b9aSAndroid Build Coastguard Worker }) 2725*e1997b9aSAndroid Build Coastguard Worker } 2726*e1997b9aSAndroid Build Coastguard Worker 2727*e1997b9aSAndroid Build Coastguard Worker /// Returns a list of KeyDescriptors in the selected domain/namespace whose 2728*e1997b9aSAndroid Build Coastguard Worker /// aliases are greater than the specified 'start_past_alias'. If no value 2729*e1997b9aSAndroid Build Coastguard Worker /// is provided, returns all KeyDescriptors. 2730*e1997b9aSAndroid Build Coastguard Worker /// The key descriptors will have the domain, nspace, and alias field set. 2731*e1997b9aSAndroid Build Coastguard Worker /// The returned list will be sorted by alias. 2732*e1997b9aSAndroid Build Coastguard Worker /// Domain must be APP or SELINUX, the caller must make sure of that. 2733*e1997b9aSAndroid Build Coastguard Worker /// Number of returned values is limited to 10,000 (which is empirically roughly 2734*e1997b9aSAndroid Build Coastguard Worker /// what will fit in a Binder message). list_past_alias( &mut self, domain: Domain, namespace: i64, key_type: KeyType, start_past_alias: Option<&str>, ) -> Result<Vec<KeyDescriptor>>2735*e1997b9aSAndroid Build Coastguard Worker pub fn list_past_alias( 2736*e1997b9aSAndroid Build Coastguard Worker &mut self, 2737*e1997b9aSAndroid Build Coastguard Worker domain: Domain, 2738*e1997b9aSAndroid Build Coastguard Worker namespace: i64, 2739*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 2740*e1997b9aSAndroid Build Coastguard Worker start_past_alias: Option<&str>, 2741*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Vec<KeyDescriptor>> { 2742*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::list_past_alias"); 2743*e1997b9aSAndroid Build Coastguard Worker 2744*e1997b9aSAndroid Build Coastguard Worker let query = format!( 2745*e1997b9aSAndroid Build Coastguard Worker "SELECT DISTINCT alias FROM persistent.keyentry 2746*e1997b9aSAndroid Build Coastguard Worker WHERE domain = ? 2747*e1997b9aSAndroid Build Coastguard Worker AND namespace = ? 2748*e1997b9aSAndroid Build Coastguard Worker AND alias IS NOT NULL 2749*e1997b9aSAndroid Build Coastguard Worker AND state = ? 2750*e1997b9aSAndroid Build Coastguard Worker AND key_type = ? 2751*e1997b9aSAndroid Build Coastguard Worker {} 2752*e1997b9aSAndroid Build Coastguard Worker ORDER BY alias ASC 2753*e1997b9aSAndroid Build Coastguard Worker LIMIT 10000;", 2754*e1997b9aSAndroid Build Coastguard Worker if start_past_alias.is_some() { " AND alias > ?" } else { "" } 2755*e1997b9aSAndroid Build Coastguard Worker ); 2756*e1997b9aSAndroid Build Coastguard Worker 2757*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(TransactionBehavior::Deferred, |tx| { 2758*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx.prepare(&query).context(ks_err!("Failed to prepare."))?; 2759*e1997b9aSAndroid Build Coastguard Worker 2760*e1997b9aSAndroid Build Coastguard Worker let mut rows = match start_past_alias { 2761*e1997b9aSAndroid Build Coastguard Worker Some(past_alias) => stmt 2762*e1997b9aSAndroid Build Coastguard Worker .query(params![ 2763*e1997b9aSAndroid Build Coastguard Worker domain.0 as u32, 2764*e1997b9aSAndroid Build Coastguard Worker namespace, 2765*e1997b9aSAndroid Build Coastguard Worker KeyLifeCycle::Live, 2766*e1997b9aSAndroid Build Coastguard Worker key_type, 2767*e1997b9aSAndroid Build Coastguard Worker past_alias 2768*e1997b9aSAndroid Build Coastguard Worker ]) 2769*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to query."))?, 2770*e1997b9aSAndroid Build Coastguard Worker None => stmt 2771*e1997b9aSAndroid Build Coastguard Worker .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live, key_type,]) 2772*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to query."))?, 2773*e1997b9aSAndroid Build Coastguard Worker }; 2774*e1997b9aSAndroid Build Coastguard Worker 2775*e1997b9aSAndroid Build Coastguard Worker let mut descriptors: Vec<KeyDescriptor> = Vec::new(); 2776*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 2777*e1997b9aSAndroid Build Coastguard Worker descriptors.push(KeyDescriptor { 2778*e1997b9aSAndroid Build Coastguard Worker domain, 2779*e1997b9aSAndroid Build Coastguard Worker nspace: namespace, 2780*e1997b9aSAndroid Build Coastguard Worker alias: Some(row.get(0).context("Trying to extract alias.")?), 2781*e1997b9aSAndroid Build Coastguard Worker blob: None, 2782*e1997b9aSAndroid Build Coastguard Worker }); 2783*e1997b9aSAndroid Build Coastguard Worker Ok(()) 2784*e1997b9aSAndroid Build Coastguard Worker }) 2785*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to extract rows."))?; 2786*e1997b9aSAndroid Build Coastguard Worker Ok(descriptors).no_gc() 2787*e1997b9aSAndroid Build Coastguard Worker }) 2788*e1997b9aSAndroid Build Coastguard Worker } 2789*e1997b9aSAndroid Build Coastguard Worker 2790*e1997b9aSAndroid Build Coastguard Worker /// Returns a number of KeyDescriptors in the selected domain/namespace. 2791*e1997b9aSAndroid Build Coastguard Worker /// Domain must be APP or SELINUX, the caller must make sure of that. count_keys( &mut self, domain: Domain, namespace: i64, key_type: KeyType, ) -> Result<usize>2792*e1997b9aSAndroid Build Coastguard Worker pub fn count_keys( 2793*e1997b9aSAndroid Build Coastguard Worker &mut self, 2794*e1997b9aSAndroid Build Coastguard Worker domain: Domain, 2795*e1997b9aSAndroid Build Coastguard Worker namespace: i64, 2796*e1997b9aSAndroid Build Coastguard Worker key_type: KeyType, 2797*e1997b9aSAndroid Build Coastguard Worker ) -> Result<usize> { 2798*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::countKeys"); 2799*e1997b9aSAndroid Build Coastguard Worker 2800*e1997b9aSAndroid Build Coastguard Worker let num_keys = self.with_transaction(TransactionBehavior::Deferred, |tx| { 2801*e1997b9aSAndroid Build Coastguard Worker tx.query_row( 2802*e1997b9aSAndroid Build Coastguard Worker "SELECT COUNT(alias) FROM persistent.keyentry 2803*e1997b9aSAndroid Build Coastguard Worker WHERE domain = ? 2804*e1997b9aSAndroid Build Coastguard Worker AND namespace = ? 2805*e1997b9aSAndroid Build Coastguard Worker AND alias IS NOT NULL 2806*e1997b9aSAndroid Build Coastguard Worker AND state = ? 2807*e1997b9aSAndroid Build Coastguard Worker AND key_type = ?;", 2808*e1997b9aSAndroid Build Coastguard Worker params![domain.0 as u32, namespace, KeyLifeCycle::Live, key_type], 2809*e1997b9aSAndroid Build Coastguard Worker |row| row.get(0), 2810*e1997b9aSAndroid Build Coastguard Worker ) 2811*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to count number of keys.")) 2812*e1997b9aSAndroid Build Coastguard Worker .no_gc() 2813*e1997b9aSAndroid Build Coastguard Worker })?; 2814*e1997b9aSAndroid Build Coastguard Worker Ok(num_keys) 2815*e1997b9aSAndroid Build Coastguard Worker } 2816*e1997b9aSAndroid Build Coastguard Worker 2817*e1997b9aSAndroid Build Coastguard Worker /// Adds a grant to the grant table. 2818*e1997b9aSAndroid Build Coastguard Worker /// Like `load_key_entry` this function loads the access tuple before 2819*e1997b9aSAndroid Build Coastguard Worker /// it uses the callback for a permission check. Upon success, 2820*e1997b9aSAndroid Build Coastguard Worker /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the 2821*e1997b9aSAndroid Build Coastguard Worker /// grant table. The new row will have a randomized id, which is used as 2822*e1997b9aSAndroid Build Coastguard Worker /// 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>2823*e1997b9aSAndroid Build Coastguard Worker pub fn grant( 2824*e1997b9aSAndroid Build Coastguard Worker &mut self, 2825*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 2826*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 2827*e1997b9aSAndroid Build Coastguard Worker grantee_uid: u32, 2828*e1997b9aSAndroid Build Coastguard Worker access_vector: KeyPermSet, 2829*e1997b9aSAndroid Build Coastguard Worker check_permission: impl Fn(&KeyDescriptor, &KeyPermSet) -> Result<()>, 2830*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyDescriptor> { 2831*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::grant"); 2832*e1997b9aSAndroid Build Coastguard Worker 2833*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_grant"), |tx| { 2834*e1997b9aSAndroid Build Coastguard Worker // Load the key_id and complete the access control tuple. 2835*e1997b9aSAndroid Build Coastguard Worker // We ignore the access vector here because grants cannot be granted. 2836*e1997b9aSAndroid Build Coastguard Worker // The access vector returned here expresses the permissions the 2837*e1997b9aSAndroid Build Coastguard Worker // grantee has if key.domain == Domain::GRANT. But this vector 2838*e1997b9aSAndroid Build Coastguard Worker // cannot include the grant permission by design, so there is no way the 2839*e1997b9aSAndroid Build Coastguard Worker // subsequent permission check can pass. 2840*e1997b9aSAndroid Build Coastguard Worker // We could check key.domain == Domain::GRANT and fail early. 2841*e1997b9aSAndroid Build Coastguard Worker // But even if we load the access tuple by grant here, the permission 2842*e1997b9aSAndroid Build Coastguard Worker // check denies the attempt to create a grant by grant descriptor. 2843*e1997b9aSAndroid Build Coastguard Worker let access = 2844*e1997b9aSAndroid Build Coastguard Worker Self::load_access_tuple(tx, key, KeyType::Client, caller_uid).context(ks_err!())?; 2845*e1997b9aSAndroid Build Coastguard Worker 2846*e1997b9aSAndroid Build Coastguard Worker // Perform access control. It is vital that we return here if the permission 2847*e1997b9aSAndroid Build Coastguard Worker // was denied. So do not touch that '?' at the end of the line. 2848*e1997b9aSAndroid Build Coastguard Worker // This permission check checks if the caller has the grant permission 2849*e1997b9aSAndroid Build Coastguard Worker // for the given key and in addition to all of the permissions 2850*e1997b9aSAndroid Build Coastguard Worker // expressed in `access_vector`. 2851*e1997b9aSAndroid Build Coastguard Worker check_permission(&access.descriptor, &access_vector) 2852*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("check_permission failed"))?; 2853*e1997b9aSAndroid Build Coastguard Worker 2854*e1997b9aSAndroid Build Coastguard Worker let grant_id = if let Some(grant_id) = tx 2855*e1997b9aSAndroid Build Coastguard Worker .query_row( 2856*e1997b9aSAndroid Build Coastguard Worker "SELECT id FROM persistent.grant 2857*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ? AND grantee = ?;", 2858*e1997b9aSAndroid Build Coastguard Worker params![access.key_id, grantee_uid], 2859*e1997b9aSAndroid Build Coastguard Worker |row| row.get(0), 2860*e1997b9aSAndroid Build Coastguard Worker ) 2861*e1997b9aSAndroid Build Coastguard Worker .optional() 2862*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed get optional existing grant id."))? 2863*e1997b9aSAndroid Build Coastguard Worker { 2864*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2865*e1997b9aSAndroid Build Coastguard Worker "UPDATE persistent.grant 2866*e1997b9aSAndroid Build Coastguard Worker SET access_vector = ? 2867*e1997b9aSAndroid Build Coastguard Worker WHERE id = ?;", 2868*e1997b9aSAndroid Build Coastguard Worker params![i32::from(access_vector), grant_id], 2869*e1997b9aSAndroid Build Coastguard Worker ) 2870*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to update existing grant."))?; 2871*e1997b9aSAndroid Build Coastguard Worker grant_id 2872*e1997b9aSAndroid Build Coastguard Worker } else { 2873*e1997b9aSAndroid Build Coastguard Worker Self::insert_with_retry(|id| { 2874*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2875*e1997b9aSAndroid Build Coastguard Worker "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector) 2876*e1997b9aSAndroid Build Coastguard Worker VALUES (?, ?, ?, ?);", 2877*e1997b9aSAndroid Build Coastguard Worker params![id, grantee_uid, access.key_id, i32::from(access_vector)], 2878*e1997b9aSAndroid Build Coastguard Worker ) 2879*e1997b9aSAndroid Build Coastguard Worker }) 2880*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!())? 2881*e1997b9aSAndroid Build Coastguard Worker }; 2882*e1997b9aSAndroid Build Coastguard Worker 2883*e1997b9aSAndroid Build Coastguard Worker Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None }) 2884*e1997b9aSAndroid Build Coastguard Worker .no_gc() 2885*e1997b9aSAndroid Build Coastguard Worker }) 2886*e1997b9aSAndroid Build Coastguard Worker } 2887*e1997b9aSAndroid Build Coastguard Worker 2888*e1997b9aSAndroid Build Coastguard Worker /// This function checks permissions like `grant` and `load_key_entry` 2889*e1997b9aSAndroid Build Coastguard Worker /// 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<()>2890*e1997b9aSAndroid Build Coastguard Worker pub fn ungrant( 2891*e1997b9aSAndroid Build Coastguard Worker &mut self, 2892*e1997b9aSAndroid Build Coastguard Worker key: &KeyDescriptor, 2893*e1997b9aSAndroid Build Coastguard Worker caller_uid: u32, 2894*e1997b9aSAndroid Build Coastguard Worker grantee_uid: u32, 2895*e1997b9aSAndroid Build Coastguard Worker check_permission: impl Fn(&KeyDescriptor) -> Result<()>, 2896*e1997b9aSAndroid Build Coastguard Worker ) -> Result<()> { 2897*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::ungrant"); 2898*e1997b9aSAndroid Build Coastguard Worker 2899*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_ungrant"), |tx| { 2900*e1997b9aSAndroid Build Coastguard Worker // Load the key_id and complete the access control tuple. 2901*e1997b9aSAndroid Build Coastguard Worker // We ignore the access vector here because grants cannot be granted. 2902*e1997b9aSAndroid Build Coastguard Worker let access = 2903*e1997b9aSAndroid Build Coastguard Worker Self::load_access_tuple(tx, key, KeyType::Client, caller_uid).context(ks_err!())?; 2904*e1997b9aSAndroid Build Coastguard Worker 2905*e1997b9aSAndroid Build Coastguard Worker // Perform access control. We must return here if the permission 2906*e1997b9aSAndroid Build Coastguard Worker // was denied. So do not touch the '?' at the end of this line. 2907*e1997b9aSAndroid Build Coastguard Worker check_permission(&access.descriptor).context(ks_err!("check_permission failed."))?; 2908*e1997b9aSAndroid Build Coastguard Worker 2909*e1997b9aSAndroid Build Coastguard Worker tx.execute( 2910*e1997b9aSAndroid Build Coastguard Worker "DELETE FROM persistent.grant 2911*e1997b9aSAndroid Build Coastguard Worker WHERE keyentryid = ? AND grantee = ?;", 2912*e1997b9aSAndroid Build Coastguard Worker params![access.key_id, grantee_uid], 2913*e1997b9aSAndroid Build Coastguard Worker ) 2914*e1997b9aSAndroid Build Coastguard Worker .context("Failed to delete grant.")?; 2915*e1997b9aSAndroid Build Coastguard Worker 2916*e1997b9aSAndroid Build Coastguard Worker Ok(()).no_gc() 2917*e1997b9aSAndroid Build Coastguard Worker }) 2918*e1997b9aSAndroid Build Coastguard Worker } 2919*e1997b9aSAndroid Build Coastguard Worker 2920*e1997b9aSAndroid Build Coastguard Worker // Generates a random id and passes it to the given function, which will 2921*e1997b9aSAndroid Build Coastguard Worker // try to insert it into a database. If that insertion fails, retry; 2922*e1997b9aSAndroid Build Coastguard Worker // otherwise return the id. insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64>2923*e1997b9aSAndroid Build Coastguard Worker fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> { 2924*e1997b9aSAndroid Build Coastguard Worker loop { 2925*e1997b9aSAndroid Build Coastguard Worker let newid: i64 = match random() { 2926*e1997b9aSAndroid Build Coastguard Worker Self::UNASSIGNED_KEY_ID => continue, // UNASSIGNED_KEY_ID cannot be assigned. 2927*e1997b9aSAndroid Build Coastguard Worker i => i, 2928*e1997b9aSAndroid Build Coastguard Worker }; 2929*e1997b9aSAndroid Build Coastguard Worker match inserter(newid) { 2930*e1997b9aSAndroid Build Coastguard Worker // If the id already existed, try again. 2931*e1997b9aSAndroid Build Coastguard Worker Err(rusqlite::Error::SqliteFailure( 2932*e1997b9aSAndroid Build Coastguard Worker libsqlite3_sys::Error { 2933*e1997b9aSAndroid Build Coastguard Worker code: libsqlite3_sys::ErrorCode::ConstraintViolation, 2934*e1997b9aSAndroid Build Coastguard Worker extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE, 2935*e1997b9aSAndroid Build Coastguard Worker }, 2936*e1997b9aSAndroid Build Coastguard Worker _, 2937*e1997b9aSAndroid Build Coastguard Worker )) => (), 2938*e1997b9aSAndroid Build Coastguard Worker Err(e) => { 2939*e1997b9aSAndroid Build Coastguard Worker return Err(e).context(ks_err!("failed to insert into database.")); 2940*e1997b9aSAndroid Build Coastguard Worker } 2941*e1997b9aSAndroid Build Coastguard Worker _ => return Ok(newid), 2942*e1997b9aSAndroid Build Coastguard Worker } 2943*e1997b9aSAndroid Build Coastguard Worker } 2944*e1997b9aSAndroid Build Coastguard Worker } 2945*e1997b9aSAndroid Build Coastguard Worker 2946*e1997b9aSAndroid Build Coastguard Worker /// Insert or replace the auth token based on (user_id, auth_id, auth_type) insert_auth_token(&mut self, auth_token: &HardwareAuthToken)2947*e1997b9aSAndroid Build Coastguard Worker pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) { 2948*e1997b9aSAndroid Build Coastguard Worker self.perboot 2949*e1997b9aSAndroid Build Coastguard Worker .insert_auth_token_entry(AuthTokenEntry::new(auth_token.clone(), BootTime::now())) 2950*e1997b9aSAndroid Build Coastguard Worker } 2951*e1997b9aSAndroid Build Coastguard Worker 2952*e1997b9aSAndroid Build Coastguard Worker /// Find the newest auth token matching the given predicate. find_auth_token_entry<F>(&self, p: F) -> Option<AuthTokenEntry> where F: Fn(&AuthTokenEntry) -> bool,2953*e1997b9aSAndroid Build Coastguard Worker pub fn find_auth_token_entry<F>(&self, p: F) -> Option<AuthTokenEntry> 2954*e1997b9aSAndroid Build Coastguard Worker where 2955*e1997b9aSAndroid Build Coastguard Worker F: Fn(&AuthTokenEntry) -> bool, 2956*e1997b9aSAndroid Build Coastguard Worker { 2957*e1997b9aSAndroid Build Coastguard Worker self.perboot.find_auth_token_entry(p) 2958*e1997b9aSAndroid Build Coastguard Worker } 2959*e1997b9aSAndroid Build Coastguard Worker 2960*e1997b9aSAndroid Build Coastguard Worker /// Load descriptor of a key by key id load_key_descriptor(&mut self, key_id: i64) -> Result<Option<KeyDescriptor>>2961*e1997b9aSAndroid Build Coastguard Worker pub fn load_key_descriptor(&mut self, key_id: i64) -> Result<Option<KeyDescriptor>> { 2962*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::load_key_descriptor"); 2963*e1997b9aSAndroid Build Coastguard Worker 2964*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(TransactionBehavior::Deferred, |tx| { 2965*e1997b9aSAndroid Build Coastguard Worker tx.query_row( 2966*e1997b9aSAndroid Build Coastguard Worker "SELECT domain, namespace, alias FROM persistent.keyentry WHERE id = ?;", 2967*e1997b9aSAndroid Build Coastguard Worker params![key_id], 2968*e1997b9aSAndroid Build Coastguard Worker |row| { 2969*e1997b9aSAndroid Build Coastguard Worker Ok(KeyDescriptor { 2970*e1997b9aSAndroid Build Coastguard Worker domain: Domain(row.get(0)?), 2971*e1997b9aSAndroid Build Coastguard Worker nspace: row.get(1)?, 2972*e1997b9aSAndroid Build Coastguard Worker alias: row.get(2)?, 2973*e1997b9aSAndroid Build Coastguard Worker blob: None, 2974*e1997b9aSAndroid Build Coastguard Worker }) 2975*e1997b9aSAndroid Build Coastguard Worker }, 2976*e1997b9aSAndroid Build Coastguard Worker ) 2977*e1997b9aSAndroid Build Coastguard Worker .optional() 2978*e1997b9aSAndroid Build Coastguard Worker .context("Trying to load key descriptor") 2979*e1997b9aSAndroid Build Coastguard Worker .no_gc() 2980*e1997b9aSAndroid Build Coastguard Worker }) 2981*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!()) 2982*e1997b9aSAndroid Build Coastguard Worker } 2983*e1997b9aSAndroid Build Coastguard Worker 2984*e1997b9aSAndroid Build Coastguard Worker /// Returns a list of app UIDs that have keys authenticated by the given secure_user_id 2985*e1997b9aSAndroid Build Coastguard Worker /// (for the given user_id). 2986*e1997b9aSAndroid Build Coastguard Worker /// This is helpful for finding out which apps will have their keys invalidated when 2987*e1997b9aSAndroid Build Coastguard Worker /// the user changes biometrics enrollment or removes their LSKF. get_app_uids_affected_by_sid( &mut self, user_id: i32, secure_user_id: i64, ) -> Result<Vec<i64>>2988*e1997b9aSAndroid Build Coastguard Worker pub fn get_app_uids_affected_by_sid( 2989*e1997b9aSAndroid Build Coastguard Worker &mut self, 2990*e1997b9aSAndroid Build Coastguard Worker user_id: i32, 2991*e1997b9aSAndroid Build Coastguard Worker secure_user_id: i64, 2992*e1997b9aSAndroid Build Coastguard Worker ) -> Result<Vec<i64>> { 2993*e1997b9aSAndroid Build Coastguard Worker let _wp = wd::watch("KeystoreDB::get_app_uids_affected_by_sid"); 2994*e1997b9aSAndroid Build Coastguard Worker 2995*e1997b9aSAndroid Build Coastguard Worker let ids = self.with_transaction(Immediate("TX_get_app_uids_affected_by_sid"), |tx| { 2996*e1997b9aSAndroid Build Coastguard Worker let mut stmt = tx 2997*e1997b9aSAndroid Build Coastguard Worker .prepare(&format!( 2998*e1997b9aSAndroid Build Coastguard Worker "SELECT id, namespace from persistent.keyentry 2999*e1997b9aSAndroid Build Coastguard Worker WHERE key_type = ? 3000*e1997b9aSAndroid Build Coastguard Worker AND domain = ? 3001*e1997b9aSAndroid Build Coastguard Worker AND cast ( (namespace/{AID_USER_OFFSET}) as int) = ? 3002*e1997b9aSAndroid Build Coastguard Worker AND state = ?;", 3003*e1997b9aSAndroid Build Coastguard Worker )) 3004*e1997b9aSAndroid Build Coastguard Worker .context(concat!( 3005*e1997b9aSAndroid Build Coastguard Worker "In get_app_uids_affected_by_sid, ", 3006*e1997b9aSAndroid Build Coastguard Worker "failed to prepare the query to find the keys created by apps." 3007*e1997b9aSAndroid Build Coastguard Worker ))?; 3008*e1997b9aSAndroid Build Coastguard Worker 3009*e1997b9aSAndroid Build Coastguard Worker let mut rows = stmt 3010*e1997b9aSAndroid Build Coastguard Worker .query(params![KeyType::Client, Domain::APP.0 as u32, user_id, KeyLifeCycle::Live,]) 3011*e1997b9aSAndroid Build Coastguard Worker .context(ks_err!("Failed to query the keys created by apps."))?; 3012*e1997b9aSAndroid Build Coastguard Worker 3013*e1997b9aSAndroid Build Coastguard Worker let mut key_ids_and_app_uids: HashMap<i64, i64> = Default::default(); 3014*e1997b9aSAndroid Build Coastguard Worker db_utils::with_rows_extract_all(&mut rows, |row| { 3015*e1997b9aSAndroid Build Coastguard Worker key_ids_and_app_uids.insert( 3016*e1997b9aSAndroid Build Coastguard Worker row.get(0).context("Failed to read key id of a key created by an app.")?, 3017*e1997b9aSAndroid Build Coastguard Worker row.get(1).context("Failed to read the app uid")?, 3018*e1997b9aSAndroid Build Coastguard Worker ); 3019*e1997b9aSAndroid Build Coastguard Worker Ok(()) 3020*e1997b9aSAndroid Build Coastguard Worker })?; 3021*e1997b9aSAndroid Build Coastguard Worker Ok(key_ids_and_app_uids).no_gc() 3022*e1997b9aSAndroid Build Coastguard Worker })?; 3023*e1997b9aSAndroid Build Coastguard Worker let mut app_uids_affected_by_sid: HashSet<i64> = Default::default(); 3024*e1997b9aSAndroid Build Coastguard Worker for (key_id, app_uid) in ids { 3025*e1997b9aSAndroid Build Coastguard Worker // Read the key parameters for each key in its own transaction. It is OK to ignore 3026*e1997b9aSAndroid Build Coastguard Worker // an error to get the properties of a particular key since it might have been deleted 3027*e1997b9aSAndroid Build Coastguard Worker // under our feet after the previous transaction concluded. If the key was deleted 3028*e1997b9aSAndroid Build Coastguard Worker // then it is no longer applicable if it was auth-bound or not. 3029*e1997b9aSAndroid Build Coastguard Worker if let Ok(is_key_bound_to_sid) = 3030*e1997b9aSAndroid Build Coastguard Worker self.with_transaction(Immediate("TX_get_app_uids_affects_by_sid 2"), |tx| { 3031*e1997b9aSAndroid Build Coastguard Worker let params = Self::load_key_parameters(key_id, tx) 3032*e1997b9aSAndroid Build Coastguard Worker .context("Failed to load key parameters.")?; 3033*e1997b9aSAndroid Build Coastguard Worker // Check if the key is bound to this secure user ID. 3034*e1997b9aSAndroid Build Coastguard Worker let is_key_bound_to_sid = params.iter().any(|kp| { 3035*e1997b9aSAndroid Build Coastguard Worker matches!( 3036*e1997b9aSAndroid Build Coastguard Worker kp.key_parameter_value(), 3037*e1997b9aSAndroid Build Coastguard Worker KeyParameterValue::UserSecureID(sid) if *sid == secure_user_id 3038*e1997b9aSAndroid Build Coastguard Worker ) 3039*e1997b9aSAndroid Build Coastguard Worker }); 3040*e1997b9aSAndroid Build Coastguard Worker Ok(is_key_bound_to_sid).no_gc() 3041*e1997b9aSAndroid Build Coastguard Worker }) 3042*e1997b9aSAndroid Build Coastguard Worker { 3043*e1997b9aSAndroid Build Coastguard Worker if is_key_bound_to_sid { 3044*e1997b9aSAndroid Build Coastguard Worker app_uids_affected_by_sid.insert(app_uid); 3045*e1997b9aSAndroid Build Coastguard Worker } 3046*e1997b9aSAndroid Build Coastguard Worker } 3047*e1997b9aSAndroid Build Coastguard Worker } 3048*e1997b9aSAndroid Build Coastguard Worker 3049*e1997b9aSAndroid Build Coastguard Worker let app_uids_vec: Vec<i64> = app_uids_affected_by_sid.into_iter().collect(); 3050*e1997b9aSAndroid Build Coastguard Worker Ok(app_uids_vec) 3051*e1997b9aSAndroid Build Coastguard Worker } 3052*e1997b9aSAndroid Build Coastguard Worker } 3053