xref: /aosp_15_r20/system/security/keystore2/src/database.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
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