xref: /aosp_15_r20/system/security/keystore2/src/database/tests.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 //! Database tests.
16*e1997b9aSAndroid Build Coastguard Worker 
17*e1997b9aSAndroid Build Coastguard Worker use super::*;
18*e1997b9aSAndroid Build Coastguard Worker use crate::key_parameter::{
19*e1997b9aSAndroid Build Coastguard Worker     Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
20*e1997b9aSAndroid Build Coastguard Worker     KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
21*e1997b9aSAndroid Build Coastguard Worker };
22*e1997b9aSAndroid Build Coastguard Worker use crate::key_perm_set;
23*e1997b9aSAndroid Build Coastguard Worker use crate::permission::{KeyPerm, KeyPermSet};
24*e1997b9aSAndroid Build Coastguard Worker use crate::super_key::{SuperKeyManager, USER_AFTER_FIRST_UNLOCK_SUPER_KEY, SuperEncryptionAlgorithm, SuperKeyType};
25*e1997b9aSAndroid Build Coastguard Worker use keystore2_test_utils::TempDir;
26*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
27*e1997b9aSAndroid Build Coastguard Worker     HardwareAuthToken::HardwareAuthToken,
28*e1997b9aSAndroid Build Coastguard Worker     HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
29*e1997b9aSAndroid Build Coastguard Worker };
30*e1997b9aSAndroid Build Coastguard Worker use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
31*e1997b9aSAndroid Build Coastguard Worker     Timestamp::Timestamp,
32*e1997b9aSAndroid Build Coastguard Worker };
33*e1997b9aSAndroid Build Coastguard Worker use std::cell::RefCell;
34*e1997b9aSAndroid Build Coastguard Worker use std::collections::BTreeMap;
35*e1997b9aSAndroid Build Coastguard Worker use std::fmt::Write;
36*e1997b9aSAndroid Build Coastguard Worker use std::sync::atomic::{AtomicU8, Ordering};
37*e1997b9aSAndroid Build Coastguard Worker use std::sync::Arc;
38*e1997b9aSAndroid Build Coastguard Worker use std::thread;
39*e1997b9aSAndroid Build Coastguard Worker use std::time::{Duration, SystemTime};
40*e1997b9aSAndroid Build Coastguard Worker use crate::utils::AesGcm;
41*e1997b9aSAndroid Build Coastguard Worker #[cfg(disabled)]
42*e1997b9aSAndroid Build Coastguard Worker use std::time::Instant;
43*e1997b9aSAndroid Build Coastguard Worker 
new_test_db() -> Result<KeystoreDB>44*e1997b9aSAndroid Build Coastguard Worker pub fn new_test_db() -> Result<KeystoreDB> {
45*e1997b9aSAndroid Build Coastguard Worker     new_test_db_at("file::memory:")
46*e1997b9aSAndroid Build Coastguard Worker }
47*e1997b9aSAndroid Build Coastguard Worker 
new_test_db_at(path: &str) -> Result<KeystoreDB>48*e1997b9aSAndroid Build Coastguard Worker fn new_test_db_at(path: &str) -> Result<KeystoreDB> {
49*e1997b9aSAndroid Build Coastguard Worker     let conn = KeystoreDB::make_connection(path)?;
50*e1997b9aSAndroid Build Coastguard Worker 
51*e1997b9aSAndroid Build Coastguard Worker     let mut db = KeystoreDB { conn, gc: None, perboot: Arc::new(perboot::PerbootDB::new()) };
52*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_new_test_db"), |tx| {
53*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::init_tables(tx).context("Failed to initialize tables.").no_gc()
54*e1997b9aSAndroid Build Coastguard Worker     })?;
55*e1997b9aSAndroid Build Coastguard Worker     Ok(db)
56*e1997b9aSAndroid Build Coastguard Worker }
57*e1997b9aSAndroid Build Coastguard Worker 
rebind_alias( db: &mut KeystoreDB, newid: &KeyIdGuard, alias: &str, domain: Domain, namespace: i64, ) -> Result<bool>58*e1997b9aSAndroid Build Coastguard Worker fn rebind_alias(
59*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
60*e1997b9aSAndroid Build Coastguard Worker     newid: &KeyIdGuard,
61*e1997b9aSAndroid Build Coastguard Worker     alias: &str,
62*e1997b9aSAndroid Build Coastguard Worker     domain: Domain,
63*e1997b9aSAndroid Build Coastguard Worker     namespace: i64,
64*e1997b9aSAndroid Build Coastguard Worker ) -> Result<bool> {
65*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_rebind_alias"), |tx| {
66*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::rebind_alias(tx, newid, alias, &domain, &namespace, KeyType::Client).no_gc()
67*e1997b9aSAndroid Build Coastguard Worker     })
68*e1997b9aSAndroid Build Coastguard Worker     .context(ks_err!())
69*e1997b9aSAndroid Build Coastguard Worker }
70*e1997b9aSAndroid Build Coastguard Worker 
71*e1997b9aSAndroid Build Coastguard Worker #[test]
datetime() -> Result<()>72*e1997b9aSAndroid Build Coastguard Worker fn datetime() -> Result<()> {
73*e1997b9aSAndroid Build Coastguard Worker     let conn = Connection::open_in_memory()?;
74*e1997b9aSAndroid Build Coastguard Worker     conn.execute("CREATE TABLE test (ts DATETIME);", [])?;
75*e1997b9aSAndroid Build Coastguard Worker     let now = SystemTime::now();
76*e1997b9aSAndroid Build Coastguard Worker     let duration = Duration::from_secs(1000);
77*e1997b9aSAndroid Build Coastguard Worker     let then = now.checked_sub(duration).unwrap();
78*e1997b9aSAndroid Build Coastguard Worker     let soon = now.checked_add(duration).unwrap();
79*e1997b9aSAndroid Build Coastguard Worker     conn.execute(
80*e1997b9aSAndroid Build Coastguard Worker         "INSERT INTO test (ts) VALUES (?), (?), (?);",
81*e1997b9aSAndroid Build Coastguard Worker         params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
82*e1997b9aSAndroid Build Coastguard Worker     )?;
83*e1997b9aSAndroid Build Coastguard Worker     let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
84*e1997b9aSAndroid Build Coastguard Worker     let mut rows = stmt.query([])?;
85*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
86*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
87*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
88*e1997b9aSAndroid Build Coastguard Worker     assert!(rows.next()?.is_none());
89*e1997b9aSAndroid Build Coastguard Worker     assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
90*e1997b9aSAndroid Build Coastguard Worker     assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
91*e1997b9aSAndroid Build Coastguard Worker     assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
92*e1997b9aSAndroid Build Coastguard Worker     Ok(())
93*e1997b9aSAndroid Build Coastguard Worker }
94*e1997b9aSAndroid Build Coastguard Worker 
95*e1997b9aSAndroid Build Coastguard Worker // Ensure that we're using the "injected" random function, not the real one.
96*e1997b9aSAndroid Build Coastguard Worker #[test]
test_mocked_random()97*e1997b9aSAndroid Build Coastguard Worker fn test_mocked_random() {
98*e1997b9aSAndroid Build Coastguard Worker     let rand1 = random();
99*e1997b9aSAndroid Build Coastguard Worker     let rand2 = random();
100*e1997b9aSAndroid Build Coastguard Worker     let rand3 = random();
101*e1997b9aSAndroid Build Coastguard Worker     if rand1 == rand2 {
102*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(rand2 + 1, rand3);
103*e1997b9aSAndroid Build Coastguard Worker     } else {
104*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(rand1 + 1, rand2);
105*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(rand2, rand3);
106*e1997b9aSAndroid Build Coastguard Worker     }
107*e1997b9aSAndroid Build Coastguard Worker }
108*e1997b9aSAndroid Build Coastguard Worker 
109*e1997b9aSAndroid Build Coastguard Worker // Test that we have the correct tables.
110*e1997b9aSAndroid Build Coastguard Worker #[test]
test_tables() -> Result<()>111*e1997b9aSAndroid Build Coastguard Worker fn test_tables() -> Result<()> {
112*e1997b9aSAndroid Build Coastguard Worker     let db = new_test_db()?;
113*e1997b9aSAndroid Build Coastguard Worker     let tables = db
114*e1997b9aSAndroid Build Coastguard Worker         .conn
115*e1997b9aSAndroid Build Coastguard Worker         .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
116*e1997b9aSAndroid Build Coastguard Worker         .query_map(params![], |row| row.get(0))?
117*e1997b9aSAndroid Build Coastguard Worker         .collect::<rusqlite::Result<Vec<String>>>()?;
118*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables.len(), 6);
119*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables[0], "blobentry");
120*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables[1], "blobmetadata");
121*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables[2], "grant");
122*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables[3], "keyentry");
123*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables[4], "keymetadata");
124*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(tables[5], "keyparameter");
125*e1997b9aSAndroid Build Coastguard Worker     Ok(())
126*e1997b9aSAndroid Build Coastguard Worker }
127*e1997b9aSAndroid Build Coastguard Worker 
128*e1997b9aSAndroid Build Coastguard Worker #[test]
test_auth_token_table_invariant() -> Result<()>129*e1997b9aSAndroid Build Coastguard Worker fn test_auth_token_table_invariant() -> Result<()> {
130*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
131*e1997b9aSAndroid Build Coastguard Worker     let auth_token1 = HardwareAuthToken {
132*e1997b9aSAndroid Build Coastguard Worker         challenge: i64::MAX,
133*e1997b9aSAndroid Build Coastguard Worker         userId: 200,
134*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 200,
135*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
136*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 500 },
137*e1997b9aSAndroid Build Coastguard Worker         mac: String::from("mac").into_bytes(),
138*e1997b9aSAndroid Build Coastguard Worker     };
139*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&auth_token1);
140*e1997b9aSAndroid Build Coastguard Worker     let auth_tokens_returned = get_auth_tokens(&db);
141*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(auth_tokens_returned.len(), 1);
142*e1997b9aSAndroid Build Coastguard Worker 
143*e1997b9aSAndroid Build Coastguard Worker     // insert another auth token with the same values for the columns in the UNIQUE constraint
144*e1997b9aSAndroid Build Coastguard Worker     // of the auth token table and different value for timestamp
145*e1997b9aSAndroid Build Coastguard Worker     let auth_token2 = HardwareAuthToken {
146*e1997b9aSAndroid Build Coastguard Worker         challenge: i64::MAX,
147*e1997b9aSAndroid Build Coastguard Worker         userId: 200,
148*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 200,
149*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
150*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 600 },
151*e1997b9aSAndroid Build Coastguard Worker         mac: String::from("mac").into_bytes(),
152*e1997b9aSAndroid Build Coastguard Worker     };
153*e1997b9aSAndroid Build Coastguard Worker 
154*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&auth_token2);
155*e1997b9aSAndroid Build Coastguard Worker     let mut auth_tokens_returned = get_auth_tokens(&db);
156*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(auth_tokens_returned.len(), 1);
157*e1997b9aSAndroid Build Coastguard Worker 
158*e1997b9aSAndroid Build Coastguard Worker     if let Some(auth_token) = auth_tokens_returned.pop() {
159*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
160*e1997b9aSAndroid Build Coastguard Worker     }
161*e1997b9aSAndroid Build Coastguard Worker 
162*e1997b9aSAndroid Build Coastguard Worker     // insert another auth token with the different values for the columns in the UNIQUE
163*e1997b9aSAndroid Build Coastguard Worker     // constraint of the auth token table
164*e1997b9aSAndroid Build Coastguard Worker     let auth_token3 = HardwareAuthToken {
165*e1997b9aSAndroid Build Coastguard Worker         challenge: i64::MAX,
166*e1997b9aSAndroid Build Coastguard Worker         userId: 201,
167*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 200,
168*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
169*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 600 },
170*e1997b9aSAndroid Build Coastguard Worker         mac: String::from("mac").into_bytes(),
171*e1997b9aSAndroid Build Coastguard Worker     };
172*e1997b9aSAndroid Build Coastguard Worker 
173*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&auth_token3);
174*e1997b9aSAndroid Build Coastguard Worker     let auth_tokens_returned = get_auth_tokens(&db);
175*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(auth_tokens_returned.len(), 2);
176*e1997b9aSAndroid Build Coastguard Worker 
177*e1997b9aSAndroid Build Coastguard Worker     Ok(())
178*e1997b9aSAndroid Build Coastguard Worker }
179*e1997b9aSAndroid Build Coastguard Worker 
180*e1997b9aSAndroid Build Coastguard Worker // utility function for test_auth_token_table_invariant()
get_auth_tokens(db: &KeystoreDB) -> Vec<AuthTokenEntry>181*e1997b9aSAndroid Build Coastguard Worker fn get_auth_tokens(db: &KeystoreDB) -> Vec<AuthTokenEntry> {
182*e1997b9aSAndroid Build Coastguard Worker     db.perboot.get_all_auth_token_entries()
183*e1997b9aSAndroid Build Coastguard Worker }
184*e1997b9aSAndroid Build Coastguard Worker 
create_key_entry( db: &mut KeystoreDB, domain: &Domain, namespace: &i64, key_type: KeyType, km_uuid: &Uuid, ) -> Result<KeyIdGuard>185*e1997b9aSAndroid Build Coastguard Worker fn create_key_entry(
186*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
187*e1997b9aSAndroid Build Coastguard Worker     domain: &Domain,
188*e1997b9aSAndroid Build Coastguard Worker     namespace: &i64,
189*e1997b9aSAndroid Build Coastguard Worker     key_type: KeyType,
190*e1997b9aSAndroid Build Coastguard Worker     km_uuid: &Uuid,
191*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> {
192*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_create_key_entry"), |tx| {
193*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::create_key_entry_internal(tx, domain, namespace, key_type, km_uuid).no_gc()
194*e1997b9aSAndroid Build Coastguard Worker     })
195*e1997b9aSAndroid Build Coastguard Worker }
196*e1997b9aSAndroid Build Coastguard Worker 
197*e1997b9aSAndroid Build Coastguard Worker #[test]
test_persistence_for_files() -> Result<()>198*e1997b9aSAndroid Build Coastguard Worker fn test_persistence_for_files() -> Result<()> {
199*e1997b9aSAndroid Build Coastguard Worker     let temp_dir = TempDir::new("persistent_db_test")?;
200*e1997b9aSAndroid Build Coastguard Worker     let mut db = KeystoreDB::new(temp_dir.path(), None)?;
201*e1997b9aSAndroid Build Coastguard Worker 
202*e1997b9aSAndroid Build Coastguard Worker     create_key_entry(&mut db, &Domain::APP, &100, KeyType::Client, &KEYSTORE_UUID)?;
203*e1997b9aSAndroid Build Coastguard Worker     let entries = get_keyentry(&db)?;
204*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries.len(), 1);
205*e1997b9aSAndroid Build Coastguard Worker 
206*e1997b9aSAndroid Build Coastguard Worker     let db = KeystoreDB::new(temp_dir.path(), None)?;
207*e1997b9aSAndroid Build Coastguard Worker 
208*e1997b9aSAndroid Build Coastguard Worker     let entries_new = get_keyentry(&db)?;
209*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries, entries_new);
210*e1997b9aSAndroid Build Coastguard Worker     Ok(())
211*e1997b9aSAndroid Build Coastguard Worker }
212*e1997b9aSAndroid Build Coastguard Worker 
213*e1997b9aSAndroid Build Coastguard Worker #[test]
test_create_key_entry() -> Result<()>214*e1997b9aSAndroid Build Coastguard Worker fn test_create_key_entry() -> Result<()> {
215*e1997b9aSAndroid Build Coastguard Worker     fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>, Uuid) {
216*e1997b9aSAndroid Build Coastguard Worker         (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref(), ke.km_uuid.unwrap())
217*e1997b9aSAndroid Build Coastguard Worker     }
218*e1997b9aSAndroid Build Coastguard Worker 
219*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
220*e1997b9aSAndroid Build Coastguard Worker 
221*e1997b9aSAndroid Build Coastguard Worker     create_key_entry(&mut db, &Domain::APP, &100, KeyType::Client, &KEYSTORE_UUID)?;
222*e1997b9aSAndroid Build Coastguard Worker     create_key_entry(&mut db, &Domain::SELINUX, &101, KeyType::Client, &KEYSTORE_UUID)?;
223*e1997b9aSAndroid Build Coastguard Worker 
224*e1997b9aSAndroid Build Coastguard Worker     let entries = get_keyentry(&db)?;
225*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries.len(), 2);
226*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None, KEYSTORE_UUID));
227*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None, KEYSTORE_UUID));
228*e1997b9aSAndroid Build Coastguard Worker 
229*e1997b9aSAndroid Build Coastguard Worker     // Test that we must pass in a valid Domain.
230*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
231*e1997b9aSAndroid Build Coastguard Worker         create_key_entry(&mut db, &Domain::GRANT, &102, KeyType::Client, &KEYSTORE_UUID),
232*e1997b9aSAndroid Build Coastguard Worker         &format!("Domain {:?} must be either App or SELinux.", Domain::GRANT),
233*e1997b9aSAndroid Build Coastguard Worker     );
234*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
235*e1997b9aSAndroid Build Coastguard Worker         create_key_entry(&mut db, &Domain::BLOB, &103, KeyType::Client, &KEYSTORE_UUID),
236*e1997b9aSAndroid Build Coastguard Worker         &format!("Domain {:?} must be either App or SELinux.", Domain::BLOB),
237*e1997b9aSAndroid Build Coastguard Worker     );
238*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
239*e1997b9aSAndroid Build Coastguard Worker         create_key_entry(&mut db, &Domain::KEY_ID, &104, KeyType::Client, &KEYSTORE_UUID),
240*e1997b9aSAndroid Build Coastguard Worker         &format!("Domain {:?} must be either App or SELinux.", Domain::KEY_ID),
241*e1997b9aSAndroid Build Coastguard Worker     );
242*e1997b9aSAndroid Build Coastguard Worker 
243*e1997b9aSAndroid Build Coastguard Worker     Ok(())
244*e1997b9aSAndroid Build Coastguard Worker }
245*e1997b9aSAndroid Build Coastguard Worker 
246*e1997b9aSAndroid Build Coastguard Worker #[test]
test_rebind_alias() -> Result<()>247*e1997b9aSAndroid Build Coastguard Worker fn test_rebind_alias() -> Result<()> {
248*e1997b9aSAndroid Build Coastguard Worker     fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>, Option<Uuid>) {
249*e1997b9aSAndroid Build Coastguard Worker         (ke.domain, ke.namespace, ke.alias.as_deref(), ke.km_uuid)
250*e1997b9aSAndroid Build Coastguard Worker     }
251*e1997b9aSAndroid Build Coastguard Worker 
252*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
253*e1997b9aSAndroid Build Coastguard Worker     create_key_entry(&mut db, &Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?;
254*e1997b9aSAndroid Build Coastguard Worker     create_key_entry(&mut db, &Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?;
255*e1997b9aSAndroid Build Coastguard Worker     let entries = get_keyentry(&db)?;
256*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries.len(), 2);
257*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID)));
258*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID)));
259*e1997b9aSAndroid Build Coastguard Worker 
260*e1997b9aSAndroid Build Coastguard Worker     // Test that the first call to rebind_alias sets the alias.
261*e1997b9aSAndroid Build Coastguard Worker     rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
262*e1997b9aSAndroid Build Coastguard Worker     let entries = get_keyentry(&db)?;
263*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries.len(), 2);
264*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
265*e1997b9aSAndroid Build Coastguard Worker         extractor(&entries[0]),
266*e1997b9aSAndroid Build Coastguard Worker         (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID))
267*e1997b9aSAndroid Build Coastguard Worker     );
268*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID)));
269*e1997b9aSAndroid Build Coastguard Worker 
270*e1997b9aSAndroid Build Coastguard Worker     // Test that the second call to rebind_alias also empties the old one.
271*e1997b9aSAndroid Build Coastguard Worker     rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
272*e1997b9aSAndroid Build Coastguard Worker     let entries = get_keyentry(&db)?;
273*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries.len(), 2);
274*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[0]), (None, None, None, Some(KEYSTORE_UUID)));
275*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
276*e1997b9aSAndroid Build Coastguard Worker         extractor(&entries[1]),
277*e1997b9aSAndroid Build Coastguard Worker         (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID))
278*e1997b9aSAndroid Build Coastguard Worker     );
279*e1997b9aSAndroid Build Coastguard Worker 
280*e1997b9aSAndroid Build Coastguard Worker     // Test that we must pass in a valid Domain.
281*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
282*e1997b9aSAndroid Build Coastguard Worker         rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
283*e1997b9aSAndroid Build Coastguard Worker         &format!("Domain {:?} must be either App or SELinux.", Domain::GRANT),
284*e1997b9aSAndroid Build Coastguard Worker     );
285*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
286*e1997b9aSAndroid Build Coastguard Worker         rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
287*e1997b9aSAndroid Build Coastguard Worker         &format!("Domain {:?} must be either App or SELinux.", Domain::BLOB),
288*e1997b9aSAndroid Build Coastguard Worker     );
289*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
290*e1997b9aSAndroid Build Coastguard Worker         rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
291*e1997b9aSAndroid Build Coastguard Worker         &format!("Domain {:?} must be either App or SELinux.", Domain::KEY_ID),
292*e1997b9aSAndroid Build Coastguard Worker     );
293*e1997b9aSAndroid Build Coastguard Worker 
294*e1997b9aSAndroid Build Coastguard Worker     // Test that we correctly handle setting an alias for something that does not exist.
295*e1997b9aSAndroid Build Coastguard Worker     check_result_is_error_containing_string(
296*e1997b9aSAndroid Build Coastguard Worker         rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
297*e1997b9aSAndroid Build Coastguard Worker         "Expected to update a single entry but instead updated 0",
298*e1997b9aSAndroid Build Coastguard Worker     );
299*e1997b9aSAndroid Build Coastguard Worker     // Test that we correctly abort the transaction in this case.
300*e1997b9aSAndroid Build Coastguard Worker     let entries = get_keyentry(&db)?;
301*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(entries.len(), 2);
302*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(extractor(&entries[0]), (None, None, None, Some(KEYSTORE_UUID)));
303*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
304*e1997b9aSAndroid Build Coastguard Worker         extractor(&entries[1]),
305*e1997b9aSAndroid Build Coastguard Worker         (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID))
306*e1997b9aSAndroid Build Coastguard Worker     );
307*e1997b9aSAndroid Build Coastguard Worker 
308*e1997b9aSAndroid Build Coastguard Worker     Ok(())
309*e1997b9aSAndroid Build Coastguard Worker }
310*e1997b9aSAndroid Build Coastguard Worker 
311*e1997b9aSAndroid Build Coastguard Worker #[test]
test_grant_ungrant() -> Result<()>312*e1997b9aSAndroid Build Coastguard Worker fn test_grant_ungrant() -> Result<()> {
313*e1997b9aSAndroid Build Coastguard Worker     const CALLER_UID: u32 = 15;
314*e1997b9aSAndroid Build Coastguard Worker     const GRANTEE_UID: u32 = 12;
315*e1997b9aSAndroid Build Coastguard Worker     const SELINUX_NAMESPACE: i64 = 7;
316*e1997b9aSAndroid Build Coastguard Worker 
317*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
318*e1997b9aSAndroid Build Coastguard Worker     db.conn.execute(
319*e1997b9aSAndroid Build Coastguard Worker         "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state, km_uuid)
320*e1997b9aSAndroid Build Coastguard Worker                 VALUES (1, 0, 0, 15, 'key', 1, ?), (2, 0, 2, 7, 'yek', 1, ?);",
321*e1997b9aSAndroid Build Coastguard Worker         params![KEYSTORE_UUID, KEYSTORE_UUID],
322*e1997b9aSAndroid Build Coastguard Worker     )?;
323*e1997b9aSAndroid Build Coastguard Worker     let app_key = KeyDescriptor {
324*e1997b9aSAndroid Build Coastguard Worker         domain: super::Domain::APP,
325*e1997b9aSAndroid Build Coastguard Worker         nspace: 0,
326*e1997b9aSAndroid Build Coastguard Worker         alias: Some("key".to_string()),
327*e1997b9aSAndroid Build Coastguard Worker         blob: None,
328*e1997b9aSAndroid Build Coastguard Worker     };
329*e1997b9aSAndroid Build Coastguard Worker     const PVEC1: KeyPermSet = key_perm_set![KeyPerm::Use, KeyPerm::GetInfo];
330*e1997b9aSAndroid Build Coastguard Worker     const PVEC2: KeyPermSet = key_perm_set![KeyPerm::Use];
331*e1997b9aSAndroid Build Coastguard Worker 
332*e1997b9aSAndroid Build Coastguard Worker     // Reset totally predictable random number generator in case we
333*e1997b9aSAndroid Build Coastguard Worker     // are not the first test running on this thread.
334*e1997b9aSAndroid Build Coastguard Worker     reset_random();
335*e1997b9aSAndroid Build Coastguard Worker     let next_random = 0i64;
336*e1997b9aSAndroid Build Coastguard Worker 
337*e1997b9aSAndroid Build Coastguard Worker     let app_granted_key = db
338*e1997b9aSAndroid Build Coastguard Worker         .grant(&app_key, CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
339*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(*a, PVEC1);
340*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(
341*e1997b9aSAndroid Build Coastguard Worker                 *k,
342*e1997b9aSAndroid Build Coastguard Worker                 KeyDescriptor {
343*e1997b9aSAndroid Build Coastguard Worker                     domain: super::Domain::APP,
344*e1997b9aSAndroid Build Coastguard Worker                     // namespace must be set to the caller_uid.
345*e1997b9aSAndroid Build Coastguard Worker                     nspace: CALLER_UID as i64,
346*e1997b9aSAndroid Build Coastguard Worker                     alias: Some("key".to_string()),
347*e1997b9aSAndroid Build Coastguard Worker                     blob: None,
348*e1997b9aSAndroid Build Coastguard Worker                 }
349*e1997b9aSAndroid Build Coastguard Worker             );
350*e1997b9aSAndroid Build Coastguard Worker             Ok(())
351*e1997b9aSAndroid Build Coastguard Worker         })
352*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
353*e1997b9aSAndroid Build Coastguard Worker 
354*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
355*e1997b9aSAndroid Build Coastguard Worker         app_granted_key,
356*e1997b9aSAndroid Build Coastguard Worker         KeyDescriptor {
357*e1997b9aSAndroid Build Coastguard Worker             domain: super::Domain::GRANT,
358*e1997b9aSAndroid Build Coastguard Worker             // The grantid is next_random due to the mock random number generator.
359*e1997b9aSAndroid Build Coastguard Worker             nspace: next_random,
360*e1997b9aSAndroid Build Coastguard Worker             alias: None,
361*e1997b9aSAndroid Build Coastguard Worker             blob: None,
362*e1997b9aSAndroid Build Coastguard Worker         }
363*e1997b9aSAndroid Build Coastguard Worker     );
364*e1997b9aSAndroid Build Coastguard Worker 
365*e1997b9aSAndroid Build Coastguard Worker     let selinux_key = KeyDescriptor {
366*e1997b9aSAndroid Build Coastguard Worker         domain: super::Domain::SELINUX,
367*e1997b9aSAndroid Build Coastguard Worker         nspace: SELINUX_NAMESPACE,
368*e1997b9aSAndroid Build Coastguard Worker         alias: Some("yek".to_string()),
369*e1997b9aSAndroid Build Coastguard Worker         blob: None,
370*e1997b9aSAndroid Build Coastguard Worker     };
371*e1997b9aSAndroid Build Coastguard Worker 
372*e1997b9aSAndroid Build Coastguard Worker     let selinux_granted_key = db
373*e1997b9aSAndroid Build Coastguard Worker         .grant(&selinux_key, CALLER_UID, 12, PVEC1, |k, a| {
374*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(*a, PVEC1);
375*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(
376*e1997b9aSAndroid Build Coastguard Worker                 *k,
377*e1997b9aSAndroid Build Coastguard Worker                 KeyDescriptor {
378*e1997b9aSAndroid Build Coastguard Worker                     domain: super::Domain::SELINUX,
379*e1997b9aSAndroid Build Coastguard Worker                     // namespace must be the supplied SELinux
380*e1997b9aSAndroid Build Coastguard Worker                     // namespace.
381*e1997b9aSAndroid Build Coastguard Worker                     nspace: SELINUX_NAMESPACE,
382*e1997b9aSAndroid Build Coastguard Worker                     alias: Some("yek".to_string()),
383*e1997b9aSAndroid Build Coastguard Worker                     blob: None,
384*e1997b9aSAndroid Build Coastguard Worker                 }
385*e1997b9aSAndroid Build Coastguard Worker             );
386*e1997b9aSAndroid Build Coastguard Worker             Ok(())
387*e1997b9aSAndroid Build Coastguard Worker         })
388*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
389*e1997b9aSAndroid Build Coastguard Worker 
390*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
391*e1997b9aSAndroid Build Coastguard Worker         selinux_granted_key,
392*e1997b9aSAndroid Build Coastguard Worker         KeyDescriptor {
393*e1997b9aSAndroid Build Coastguard Worker             domain: super::Domain::GRANT,
394*e1997b9aSAndroid Build Coastguard Worker             // The grantid is next_random + 1 due to the mock random number generator.
395*e1997b9aSAndroid Build Coastguard Worker             nspace: next_random + 1,
396*e1997b9aSAndroid Build Coastguard Worker             alias: None,
397*e1997b9aSAndroid Build Coastguard Worker             blob: None,
398*e1997b9aSAndroid Build Coastguard Worker         }
399*e1997b9aSAndroid Build Coastguard Worker     );
400*e1997b9aSAndroid Build Coastguard Worker 
401*e1997b9aSAndroid Build Coastguard Worker     // This should update the existing grant with PVEC2.
402*e1997b9aSAndroid Build Coastguard Worker     let selinux_granted_key = db
403*e1997b9aSAndroid Build Coastguard Worker         .grant(&selinux_key, CALLER_UID, 12, PVEC2, |k, a| {
404*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(*a, PVEC2);
405*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(
406*e1997b9aSAndroid Build Coastguard Worker                 *k,
407*e1997b9aSAndroid Build Coastguard Worker                 KeyDescriptor {
408*e1997b9aSAndroid Build Coastguard Worker                     domain: super::Domain::SELINUX,
409*e1997b9aSAndroid Build Coastguard Worker                     // namespace must be the supplied SELinux
410*e1997b9aSAndroid Build Coastguard Worker                     // namespace.
411*e1997b9aSAndroid Build Coastguard Worker                     nspace: SELINUX_NAMESPACE,
412*e1997b9aSAndroid Build Coastguard Worker                     alias: Some("yek".to_string()),
413*e1997b9aSAndroid Build Coastguard Worker                     blob: None,
414*e1997b9aSAndroid Build Coastguard Worker                 }
415*e1997b9aSAndroid Build Coastguard Worker             );
416*e1997b9aSAndroid Build Coastguard Worker             Ok(())
417*e1997b9aSAndroid Build Coastguard Worker         })
418*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
419*e1997b9aSAndroid Build Coastguard Worker 
420*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
421*e1997b9aSAndroid Build Coastguard Worker         selinux_granted_key,
422*e1997b9aSAndroid Build Coastguard Worker         KeyDescriptor {
423*e1997b9aSAndroid Build Coastguard Worker             domain: super::Domain::GRANT,
424*e1997b9aSAndroid Build Coastguard Worker             // Same grant id as before. The entry was only updated.
425*e1997b9aSAndroid Build Coastguard Worker             nspace: next_random + 1,
426*e1997b9aSAndroid Build Coastguard Worker             alias: None,
427*e1997b9aSAndroid Build Coastguard Worker             blob: None,
428*e1997b9aSAndroid Build Coastguard Worker         }
429*e1997b9aSAndroid Build Coastguard Worker     );
430*e1997b9aSAndroid Build Coastguard Worker 
431*e1997b9aSAndroid Build Coastguard Worker     {
432*e1997b9aSAndroid Build Coastguard Worker         // Limiting scope of stmt, because it borrows db.
433*e1997b9aSAndroid Build Coastguard Worker         let mut stmt = db
434*e1997b9aSAndroid Build Coastguard Worker             .conn
435*e1997b9aSAndroid Build Coastguard Worker             .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
436*e1997b9aSAndroid Build Coastguard Worker         let mut rows = stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>([], |row| {
437*e1997b9aSAndroid Build Coastguard Worker             Ok((row.get(0)?, row.get(1)?, row.get(2)?, KeyPermSet::from(row.get::<_, i32>(3)?)))
438*e1997b9aSAndroid Build Coastguard Worker         })?;
439*e1997b9aSAndroid Build Coastguard Worker 
440*e1997b9aSAndroid Build Coastguard Worker         let r = rows.next().unwrap().unwrap();
441*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
442*e1997b9aSAndroid Build Coastguard Worker         let r = rows.next().unwrap().unwrap();
443*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
444*e1997b9aSAndroid Build Coastguard Worker         assert!(rows.next().is_none());
445*e1997b9aSAndroid Build Coastguard Worker     }
446*e1997b9aSAndroid Build Coastguard Worker 
447*e1997b9aSAndroid Build Coastguard Worker     debug_dump_keyentry_table(&mut db)?;
448*e1997b9aSAndroid Build Coastguard Worker     println!("app_key {:?}", app_key);
449*e1997b9aSAndroid Build Coastguard Worker     println!("selinux_key {:?}", selinux_key);
450*e1997b9aSAndroid Build Coastguard Worker 
451*e1997b9aSAndroid Build Coastguard Worker     db.ungrant(&app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
452*e1997b9aSAndroid Build Coastguard Worker     db.ungrant(&selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
453*e1997b9aSAndroid Build Coastguard Worker 
454*e1997b9aSAndroid Build Coastguard Worker     Ok(())
455*e1997b9aSAndroid Build Coastguard Worker }
456*e1997b9aSAndroid Build Coastguard Worker 
457*e1997b9aSAndroid Build Coastguard Worker static TEST_KEY_BLOB: &[u8] = b"my test blob";
458*e1997b9aSAndroid Build Coastguard Worker static TEST_CERT_BLOB: &[u8] = b"my test cert";
459*e1997b9aSAndroid Build Coastguard Worker static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
460*e1997b9aSAndroid Build Coastguard Worker 
461*e1997b9aSAndroid Build Coastguard Worker #[test]
test_set_blob() -> Result<()>462*e1997b9aSAndroid Build Coastguard Worker fn test_set_blob() -> Result<()> {
463*e1997b9aSAndroid Build Coastguard Worker     let key_id = KEY_ID_LOCK.get(3000);
464*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
465*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
466*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID));
467*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB), Some(&blob_metadata))?;
468*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB), None)?;
469*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB), None)?;
470*e1997b9aSAndroid Build Coastguard Worker     drop(key_id);
471*e1997b9aSAndroid Build Coastguard Worker 
472*e1997b9aSAndroid Build Coastguard Worker     let mut stmt = db.conn.prepare(
473*e1997b9aSAndroid Build Coastguard Worker         "SELECT subcomponent_type, keyentryid, blob, id FROM persistent.blobentry
474*e1997b9aSAndroid Build Coastguard Worker                 ORDER BY subcomponent_type ASC;",
475*e1997b9aSAndroid Build Coastguard Worker     )?;
476*e1997b9aSAndroid Build Coastguard Worker     let mut rows = stmt.query_map::<((SubComponentType, i64, Vec<u8>), i64), _, _>([], |row| {
477*e1997b9aSAndroid Build Coastguard Worker         Ok(((row.get(0)?, row.get(1)?, row.get(2)?), row.get(3)?))
478*e1997b9aSAndroid Build Coastguard Worker     })?;
479*e1997b9aSAndroid Build Coastguard Worker     let (r, id) = rows.next().unwrap().unwrap();
480*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec()));
481*e1997b9aSAndroid Build Coastguard Worker     let (r, _) = rows.next().unwrap().unwrap();
482*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec()));
483*e1997b9aSAndroid Build Coastguard Worker     let (r, _) = rows.next().unwrap().unwrap();
484*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec()));
485*e1997b9aSAndroid Build Coastguard Worker 
486*e1997b9aSAndroid Build Coastguard Worker     drop(rows);
487*e1997b9aSAndroid Build Coastguard Worker     drop(stmt);
488*e1997b9aSAndroid Build Coastguard Worker 
489*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
490*e1997b9aSAndroid Build Coastguard Worker         db.with_transaction(Immediate("TX_test"), |tx| {
491*e1997b9aSAndroid Build Coastguard Worker             BlobMetaData::load_from_db(id, tx).no_gc()
492*e1997b9aSAndroid Build Coastguard Worker         })
493*e1997b9aSAndroid Build Coastguard Worker         .expect("Should find blob metadata."),
494*e1997b9aSAndroid Build Coastguard Worker         blob_metadata
495*e1997b9aSAndroid Build Coastguard Worker     );
496*e1997b9aSAndroid Build Coastguard Worker     Ok(())
497*e1997b9aSAndroid Build Coastguard Worker }
498*e1997b9aSAndroid Build Coastguard Worker 
499*e1997b9aSAndroid Build Coastguard Worker static TEST_ALIAS: &str = "my super duper key";
500*e1997b9aSAndroid Build Coastguard Worker 
501*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_full_keyentry_domain_app() -> Result<()>502*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
503*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
504*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None)
505*e1997b9aSAndroid Build Coastguard Worker         .context("test_insert_and_load_full_keyentry_domain_app")?
506*e1997b9aSAndroid Build Coastguard Worker         .0;
507*e1997b9aSAndroid Build Coastguard Worker     let (_key_guard, key_entry) = db
508*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
509*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
510*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
511*e1997b9aSAndroid Build Coastguard Worker                 nspace: 0,
512*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
513*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
514*e1997b9aSAndroid Build Coastguard Worker             },
515*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
516*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
517*e1997b9aSAndroid Build Coastguard Worker             1,
518*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
519*e1997b9aSAndroid Build Coastguard Worker         )
520*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
521*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
522*e1997b9aSAndroid Build Coastguard Worker 
523*e1997b9aSAndroid Build Coastguard Worker     db.unbind_key(
524*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor {
525*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::APP,
526*e1997b9aSAndroid Build Coastguard Worker             nspace: 0,
527*e1997b9aSAndroid Build Coastguard Worker             alias: Some(TEST_ALIAS.to_string()),
528*e1997b9aSAndroid Build Coastguard Worker             blob: None,
529*e1997b9aSAndroid Build Coastguard Worker         },
530*e1997b9aSAndroid Build Coastguard Worker         KeyType::Client,
531*e1997b9aSAndroid Build Coastguard Worker         1,
532*e1997b9aSAndroid Build Coastguard Worker         |_, _| Ok(()),
533*e1997b9aSAndroid Build Coastguard Worker     )
534*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
535*e1997b9aSAndroid Build Coastguard Worker 
536*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
537*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
538*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
539*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
540*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
541*e1997b9aSAndroid Build Coastguard Worker                 nspace: 0,
542*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
543*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
544*e1997b9aSAndroid Build Coastguard Worker             },
545*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
546*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
547*e1997b9aSAndroid Build Coastguard Worker             1,
548*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
549*e1997b9aSAndroid Build Coastguard Worker         )
550*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
551*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
552*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
553*e1997b9aSAndroid Build Coastguard Worker     );
554*e1997b9aSAndroid Build Coastguard Worker 
555*e1997b9aSAndroid Build Coastguard Worker     Ok(())
556*e1997b9aSAndroid Build Coastguard Worker }
557*e1997b9aSAndroid Build Coastguard Worker 
558*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_certificate_entry_domain_app() -> Result<()>559*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_certificate_entry_domain_app() -> Result<()> {
560*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
561*e1997b9aSAndroid Build Coastguard Worker 
562*e1997b9aSAndroid Build Coastguard Worker     db.store_new_certificate(
563*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor {
564*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::APP,
565*e1997b9aSAndroid Build Coastguard Worker             nspace: 1,
566*e1997b9aSAndroid Build Coastguard Worker             alias: Some(TEST_ALIAS.to_string()),
567*e1997b9aSAndroid Build Coastguard Worker             blob: None,
568*e1997b9aSAndroid Build Coastguard Worker         },
569*e1997b9aSAndroid Build Coastguard Worker         KeyType::Client,
570*e1997b9aSAndroid Build Coastguard Worker         TEST_CERT_BLOB,
571*e1997b9aSAndroid Build Coastguard Worker         &KEYSTORE_UUID,
572*e1997b9aSAndroid Build Coastguard Worker     )
573*e1997b9aSAndroid Build Coastguard Worker     .expect("Trying to insert cert.");
574*e1997b9aSAndroid Build Coastguard Worker 
575*e1997b9aSAndroid Build Coastguard Worker     let (_key_guard, mut key_entry) = db
576*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
577*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
578*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
579*e1997b9aSAndroid Build Coastguard Worker                 nspace: 1,
580*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
581*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
582*e1997b9aSAndroid Build Coastguard Worker             },
583*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
584*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::PUBLIC,
585*e1997b9aSAndroid Build Coastguard Worker             1,
586*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
587*e1997b9aSAndroid Build Coastguard Worker         )
588*e1997b9aSAndroid Build Coastguard Worker         .expect("Trying to read certificate entry.");
589*e1997b9aSAndroid Build Coastguard Worker 
590*e1997b9aSAndroid Build Coastguard Worker     assert!(key_entry.pure_cert());
591*e1997b9aSAndroid Build Coastguard Worker     assert!(key_entry.cert().is_none());
592*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry.take_cert_chain(), Some(TEST_CERT_BLOB.to_vec()));
593*e1997b9aSAndroid Build Coastguard Worker 
594*e1997b9aSAndroid Build Coastguard Worker     db.unbind_key(
595*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor {
596*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::APP,
597*e1997b9aSAndroid Build Coastguard Worker             nspace: 1,
598*e1997b9aSAndroid Build Coastguard Worker             alias: Some(TEST_ALIAS.to_string()),
599*e1997b9aSAndroid Build Coastguard Worker             blob: None,
600*e1997b9aSAndroid Build Coastguard Worker         },
601*e1997b9aSAndroid Build Coastguard Worker         KeyType::Client,
602*e1997b9aSAndroid Build Coastguard Worker         1,
603*e1997b9aSAndroid Build Coastguard Worker         |_, _| Ok(()),
604*e1997b9aSAndroid Build Coastguard Worker     )
605*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
606*e1997b9aSAndroid Build Coastguard Worker 
607*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
608*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
609*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
610*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
611*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
612*e1997b9aSAndroid Build Coastguard Worker                 nspace: 1,
613*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
614*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
615*e1997b9aSAndroid Build Coastguard Worker             },
616*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
617*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
618*e1997b9aSAndroid Build Coastguard Worker             1,
619*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
620*e1997b9aSAndroid Build Coastguard Worker         )
621*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
622*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
623*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
624*e1997b9aSAndroid Build Coastguard Worker     );
625*e1997b9aSAndroid Build Coastguard Worker 
626*e1997b9aSAndroid Build Coastguard Worker     Ok(())
627*e1997b9aSAndroid Build Coastguard Worker }
628*e1997b9aSAndroid Build Coastguard Worker 
629*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_full_keyentry_domain_selinux() -> Result<()>630*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
631*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
632*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, None)
633*e1997b9aSAndroid Build Coastguard Worker         .context("test_insert_and_load_full_keyentry_domain_selinux")?
634*e1997b9aSAndroid Build Coastguard Worker         .0;
635*e1997b9aSAndroid Build Coastguard Worker     let (_key_guard, key_entry) = db
636*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
637*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
638*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::SELINUX,
639*e1997b9aSAndroid Build Coastguard Worker                 nspace: 1,
640*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
641*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
642*e1997b9aSAndroid Build Coastguard Worker             },
643*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
644*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
645*e1997b9aSAndroid Build Coastguard Worker             1,
646*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
647*e1997b9aSAndroid Build Coastguard Worker         )
648*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
649*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
650*e1997b9aSAndroid Build Coastguard Worker 
651*e1997b9aSAndroid Build Coastguard Worker     db.unbind_key(
652*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor {
653*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::SELINUX,
654*e1997b9aSAndroid Build Coastguard Worker             nspace: 1,
655*e1997b9aSAndroid Build Coastguard Worker             alias: Some(TEST_ALIAS.to_string()),
656*e1997b9aSAndroid Build Coastguard Worker             blob: None,
657*e1997b9aSAndroid Build Coastguard Worker         },
658*e1997b9aSAndroid Build Coastguard Worker         KeyType::Client,
659*e1997b9aSAndroid Build Coastguard Worker         1,
660*e1997b9aSAndroid Build Coastguard Worker         |_, _| Ok(()),
661*e1997b9aSAndroid Build Coastguard Worker     )
662*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
663*e1997b9aSAndroid Build Coastguard Worker 
664*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
665*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
666*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
667*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
668*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::SELINUX,
669*e1997b9aSAndroid Build Coastguard Worker                 nspace: 1,
670*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
671*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
672*e1997b9aSAndroid Build Coastguard Worker             },
673*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
674*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
675*e1997b9aSAndroid Build Coastguard Worker             1,
676*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
677*e1997b9aSAndroid Build Coastguard Worker         )
678*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
679*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
680*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
681*e1997b9aSAndroid Build Coastguard Worker     );
682*e1997b9aSAndroid Build Coastguard Worker 
683*e1997b9aSAndroid Build Coastguard Worker     Ok(())
684*e1997b9aSAndroid Build Coastguard Worker }
685*e1997b9aSAndroid Build Coastguard Worker 
686*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_full_keyentry_domain_key_id() -> Result<()>687*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
688*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
689*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, None)
690*e1997b9aSAndroid Build Coastguard Worker         .context("test_insert_and_load_full_keyentry_domain_key_id")?
691*e1997b9aSAndroid Build Coastguard Worker         .0;
692*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
693*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
694*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
695*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
696*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
697*e1997b9aSAndroid Build Coastguard Worker             1,
698*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
699*e1997b9aSAndroid Build Coastguard Worker         )
700*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
701*e1997b9aSAndroid Build Coastguard Worker 
702*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
703*e1997b9aSAndroid Build Coastguard Worker 
704*e1997b9aSAndroid Build Coastguard Worker     db.unbind_key(
705*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
706*e1997b9aSAndroid Build Coastguard Worker         KeyType::Client,
707*e1997b9aSAndroid Build Coastguard Worker         1,
708*e1997b9aSAndroid Build Coastguard Worker         |_, _| Ok(()),
709*e1997b9aSAndroid Build Coastguard Worker     )
710*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
711*e1997b9aSAndroid Build Coastguard Worker 
712*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
713*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
714*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
715*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
716*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
717*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
718*e1997b9aSAndroid Build Coastguard Worker             1,
719*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
720*e1997b9aSAndroid Build Coastguard Worker         )
721*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
722*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
723*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
724*e1997b9aSAndroid Build Coastguard Worker     );
725*e1997b9aSAndroid Build Coastguard Worker 
726*e1997b9aSAndroid Build Coastguard Worker     Ok(())
727*e1997b9aSAndroid Build Coastguard Worker }
728*e1997b9aSAndroid Build Coastguard Worker 
729*e1997b9aSAndroid Build Coastguard Worker #[test]
test_check_and_update_key_usage_count_with_limited_use_key() -> Result<()>730*e1997b9aSAndroid Build Coastguard Worker fn test_check_and_update_key_usage_count_with_limited_use_key() -> Result<()> {
731*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
732*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, Some(123))
733*e1997b9aSAndroid Build Coastguard Worker         .context("test_check_and_update_key_usage_count_with_limited_use_key")?
734*e1997b9aSAndroid Build Coastguard Worker         .0;
735*e1997b9aSAndroid Build Coastguard Worker     // Update the usage count of the limited use key.
736*e1997b9aSAndroid Build Coastguard Worker     db.check_and_update_key_usage_count(key_id)?;
737*e1997b9aSAndroid Build Coastguard Worker 
738*e1997b9aSAndroid Build Coastguard Worker     let (_key_guard, key_entry) = db.load_key_entry(
739*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
740*e1997b9aSAndroid Build Coastguard Worker         KeyType::Client,
741*e1997b9aSAndroid Build Coastguard Worker         KeyEntryLoadBits::BOTH,
742*e1997b9aSAndroid Build Coastguard Worker         1,
743*e1997b9aSAndroid Build Coastguard Worker         |_k, _av| Ok(()),
744*e1997b9aSAndroid Build Coastguard Worker     )?;
745*e1997b9aSAndroid Build Coastguard Worker 
746*e1997b9aSAndroid Build Coastguard Worker     // The usage count is decremented now.
747*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, Some(122)));
748*e1997b9aSAndroid Build Coastguard Worker 
749*e1997b9aSAndroid Build Coastguard Worker     Ok(())
750*e1997b9aSAndroid Build Coastguard Worker }
751*e1997b9aSAndroid Build Coastguard Worker 
752*e1997b9aSAndroid Build Coastguard Worker #[test]
test_check_and_update_key_usage_count_with_exhausted_limited_use_key() -> Result<()>753*e1997b9aSAndroid Build Coastguard Worker fn test_check_and_update_key_usage_count_with_exhausted_limited_use_key() -> Result<()> {
754*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
755*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, Some(1))
756*e1997b9aSAndroid Build Coastguard Worker         .context("test_check_and_update_key_usage_count_with_exhausted_limited_use_key")?
757*e1997b9aSAndroid Build Coastguard Worker         .0;
758*e1997b9aSAndroid Build Coastguard Worker     // Update the usage count of the limited use key.
759*e1997b9aSAndroid Build Coastguard Worker     db.check_and_update_key_usage_count(key_id).expect(concat!(
760*e1997b9aSAndroid Build Coastguard Worker         "In test_check_and_update_key_usage_count_with_exhausted_limited_use_key: ",
761*e1997b9aSAndroid Build Coastguard Worker         "This should succeed."
762*e1997b9aSAndroid Build Coastguard Worker     ));
763*e1997b9aSAndroid Build Coastguard Worker 
764*e1997b9aSAndroid Build Coastguard Worker     // Try to update the exhausted limited use key.
765*e1997b9aSAndroid Build Coastguard Worker     let e = db.check_and_update_key_usage_count(key_id).expect_err(concat!(
766*e1997b9aSAndroid Build Coastguard Worker         "In test_check_and_update_key_usage_count_with_exhausted_limited_use_key: ",
767*e1997b9aSAndroid Build Coastguard Worker         "This should fail."
768*e1997b9aSAndroid Build Coastguard Worker     ));
769*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
770*e1997b9aSAndroid Build Coastguard Worker         &KsError::Km(ErrorCode::INVALID_KEY_BLOB),
771*e1997b9aSAndroid Build Coastguard Worker         e.root_cause().downcast_ref::<KsError>().unwrap()
772*e1997b9aSAndroid Build Coastguard Worker     );
773*e1997b9aSAndroid Build Coastguard Worker 
774*e1997b9aSAndroid Build Coastguard Worker     Ok(())
775*e1997b9aSAndroid Build Coastguard Worker }
776*e1997b9aSAndroid Build Coastguard Worker 
777*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_full_keyentry_from_grant() -> Result<()>778*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
779*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
780*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None)
781*e1997b9aSAndroid Build Coastguard Worker         .context("test_insert_and_load_full_keyentry_from_grant")?
782*e1997b9aSAndroid Build Coastguard Worker         .0;
783*e1997b9aSAndroid Build Coastguard Worker 
784*e1997b9aSAndroid Build Coastguard Worker     let granted_key = db
785*e1997b9aSAndroid Build Coastguard Worker         .grant(
786*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
787*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
788*e1997b9aSAndroid Build Coastguard Worker                 nspace: 0,
789*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(TEST_ALIAS.to_string()),
790*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
791*e1997b9aSAndroid Build Coastguard Worker             },
792*e1997b9aSAndroid Build Coastguard Worker             1,
793*e1997b9aSAndroid Build Coastguard Worker             2,
794*e1997b9aSAndroid Build Coastguard Worker             key_perm_set![KeyPerm::Use],
795*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
796*e1997b9aSAndroid Build Coastguard Worker         )
797*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
798*e1997b9aSAndroid Build Coastguard Worker 
799*e1997b9aSAndroid Build Coastguard Worker     debug_dump_grant_table(&mut db)?;
800*e1997b9aSAndroid Build Coastguard Worker 
801*e1997b9aSAndroid Build Coastguard Worker     let (_key_guard, key_entry) = db
802*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(&granted_key, KeyType::Client, KeyEntryLoadBits::BOTH, 2, |k, av| {
803*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(Domain::GRANT, k.domain);
804*e1997b9aSAndroid Build Coastguard Worker             assert!(av.unwrap().includes(KeyPerm::Use));
805*e1997b9aSAndroid Build Coastguard Worker             Ok(())
806*e1997b9aSAndroid Build Coastguard Worker         })
807*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
808*e1997b9aSAndroid Build Coastguard Worker 
809*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
810*e1997b9aSAndroid Build Coastguard Worker 
811*e1997b9aSAndroid Build Coastguard Worker     db.unbind_key(&granted_key, KeyType::Client, 2, |_, _| Ok(())).unwrap();
812*e1997b9aSAndroid Build Coastguard Worker 
813*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
814*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
815*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(&granted_key, KeyType::Client, KeyEntryLoadBits::NONE, 2, |_k, _av| Ok(
816*e1997b9aSAndroid Build Coastguard Worker             ()
817*e1997b9aSAndroid Build Coastguard Worker         ),)
818*e1997b9aSAndroid Build Coastguard Worker             .unwrap_err()
819*e1997b9aSAndroid Build Coastguard Worker             .root_cause()
820*e1997b9aSAndroid Build Coastguard Worker             .downcast_ref::<KsError>()
821*e1997b9aSAndroid Build Coastguard Worker     );
822*e1997b9aSAndroid Build Coastguard Worker 
823*e1997b9aSAndroid Build Coastguard Worker     Ok(())
824*e1997b9aSAndroid Build Coastguard Worker }
825*e1997b9aSAndroid Build Coastguard Worker 
826*e1997b9aSAndroid Build Coastguard Worker // This test attempts to load a key by key id while the caller is not the owner
827*e1997b9aSAndroid Build Coastguard Worker // but a grant exists for the given key and the caller.
828*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_full_keyentry_from_grant_by_key_id() -> Result<()>829*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_full_keyentry_from_grant_by_key_id() -> Result<()> {
830*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
831*e1997b9aSAndroid Build Coastguard Worker     const OWNER_UID: u32 = 1u32;
832*e1997b9aSAndroid Build Coastguard Worker     const GRANTEE_UID: u32 = 2u32;
833*e1997b9aSAndroid Build Coastguard Worker     const SOMEONE_ELSE_UID: u32 = 3u32;
834*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::APP, OWNER_UID as i64, TEST_ALIAS, None)
835*e1997b9aSAndroid Build Coastguard Worker         .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?
836*e1997b9aSAndroid Build Coastguard Worker         .0;
837*e1997b9aSAndroid Build Coastguard Worker 
838*e1997b9aSAndroid Build Coastguard Worker     db.grant(
839*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor {
840*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::APP,
841*e1997b9aSAndroid Build Coastguard Worker             nspace: 0,
842*e1997b9aSAndroid Build Coastguard Worker             alias: Some(TEST_ALIAS.to_string()),
843*e1997b9aSAndroid Build Coastguard Worker             blob: None,
844*e1997b9aSAndroid Build Coastguard Worker         },
845*e1997b9aSAndroid Build Coastguard Worker         OWNER_UID,
846*e1997b9aSAndroid Build Coastguard Worker         GRANTEE_UID,
847*e1997b9aSAndroid Build Coastguard Worker         key_perm_set![KeyPerm::Use],
848*e1997b9aSAndroid Build Coastguard Worker         |_k, _av| Ok(()),
849*e1997b9aSAndroid Build Coastguard Worker     )
850*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
851*e1997b9aSAndroid Build Coastguard Worker 
852*e1997b9aSAndroid Build Coastguard Worker     debug_dump_grant_table(&mut db)?;
853*e1997b9aSAndroid Build Coastguard Worker 
854*e1997b9aSAndroid Build Coastguard Worker     let id_descriptor =
855*e1997b9aSAndroid Build Coastguard Worker         KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, ..Default::default() };
856*e1997b9aSAndroid Build Coastguard Worker 
857*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
858*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
859*e1997b9aSAndroid Build Coastguard Worker             &id_descriptor,
860*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
861*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
862*e1997b9aSAndroid Build Coastguard Worker             GRANTEE_UID,
863*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
864*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
865*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(OWNER_UID as i64, k.nspace);
866*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.unwrap().includes(KeyPerm::Use));
867*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
868*e1997b9aSAndroid Build Coastguard Worker             },
869*e1997b9aSAndroid Build Coastguard Worker         )
870*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
871*e1997b9aSAndroid Build Coastguard Worker 
872*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
873*e1997b9aSAndroid Build Coastguard Worker 
874*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
875*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
876*e1997b9aSAndroid Build Coastguard Worker             &id_descriptor,
877*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
878*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
879*e1997b9aSAndroid Build Coastguard Worker             SOMEONE_ELSE_UID,
880*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
881*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
882*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(OWNER_UID as i64, k.nspace);
883*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
884*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
885*e1997b9aSAndroid Build Coastguard Worker             },
886*e1997b9aSAndroid Build Coastguard Worker         )
887*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
888*e1997b9aSAndroid Build Coastguard Worker 
889*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
890*e1997b9aSAndroid Build Coastguard Worker 
891*e1997b9aSAndroid Build Coastguard Worker     db.unbind_key(&id_descriptor, KeyType::Client, OWNER_UID, |_, _| Ok(())).unwrap();
892*e1997b9aSAndroid Build Coastguard Worker 
893*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
894*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
895*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
896*e1997b9aSAndroid Build Coastguard Worker             &id_descriptor,
897*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
898*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
899*e1997b9aSAndroid Build Coastguard Worker             GRANTEE_UID,
900*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
901*e1997b9aSAndroid Build Coastguard Worker         )
902*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
903*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
904*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
905*e1997b9aSAndroid Build Coastguard Worker     );
906*e1997b9aSAndroid Build Coastguard Worker 
907*e1997b9aSAndroid Build Coastguard Worker     Ok(())
908*e1997b9aSAndroid Build Coastguard Worker }
909*e1997b9aSAndroid Build Coastguard Worker 
910*e1997b9aSAndroid Build Coastguard Worker // Creates a key migrates it to a different location and then tries to access it by the old
911*e1997b9aSAndroid Build Coastguard Worker // and new location.
912*e1997b9aSAndroid Build Coastguard Worker #[test]
test_migrate_key_app_to_app() -> Result<()>913*e1997b9aSAndroid Build Coastguard Worker fn test_migrate_key_app_to_app() -> Result<()> {
914*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
915*e1997b9aSAndroid Build Coastguard Worker     const SOURCE_UID: u32 = 1u32;
916*e1997b9aSAndroid Build Coastguard Worker     const DESTINATION_UID: u32 = 2u32;
917*e1997b9aSAndroid Build Coastguard Worker     static SOURCE_ALIAS: &str = "SOURCE_ALIAS";
918*e1997b9aSAndroid Build Coastguard Worker     static DESTINATION_ALIAS: &str = "DESTINATION_ALIAS";
919*e1997b9aSAndroid Build Coastguard Worker     let key_id_guard =
920*e1997b9aSAndroid Build Coastguard Worker         make_test_key_entry(&mut db, Domain::APP, SOURCE_UID as i64, SOURCE_ALIAS, None)
921*e1997b9aSAndroid Build Coastguard Worker             .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?;
922*e1997b9aSAndroid Build Coastguard Worker 
923*e1997b9aSAndroid Build Coastguard Worker     let source_descriptor: KeyDescriptor = KeyDescriptor {
924*e1997b9aSAndroid Build Coastguard Worker         domain: Domain::APP,
925*e1997b9aSAndroid Build Coastguard Worker         nspace: -1,
926*e1997b9aSAndroid Build Coastguard Worker         alias: Some(SOURCE_ALIAS.to_string()),
927*e1997b9aSAndroid Build Coastguard Worker         blob: None,
928*e1997b9aSAndroid Build Coastguard Worker     };
929*e1997b9aSAndroid Build Coastguard Worker 
930*e1997b9aSAndroid Build Coastguard Worker     let destination_descriptor: KeyDescriptor = KeyDescriptor {
931*e1997b9aSAndroid Build Coastguard Worker         domain: Domain::APP,
932*e1997b9aSAndroid Build Coastguard Worker         nspace: -1,
933*e1997b9aSAndroid Build Coastguard Worker         alias: Some(DESTINATION_ALIAS.to_string()),
934*e1997b9aSAndroid Build Coastguard Worker         blob: None,
935*e1997b9aSAndroid Build Coastguard Worker     };
936*e1997b9aSAndroid Build Coastguard Worker 
937*e1997b9aSAndroid Build Coastguard Worker     let key_id = key_id_guard.id();
938*e1997b9aSAndroid Build Coastguard Worker 
939*e1997b9aSAndroid Build Coastguard Worker     db.migrate_key_namespace(key_id_guard, &destination_descriptor, DESTINATION_UID, |_k| Ok(()))
940*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
941*e1997b9aSAndroid Build Coastguard Worker 
942*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
943*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
944*e1997b9aSAndroid Build Coastguard Worker             &destination_descriptor,
945*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
946*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
947*e1997b9aSAndroid Build Coastguard Worker             DESTINATION_UID,
948*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
949*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
950*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(DESTINATION_UID as i64, k.nspace);
951*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
952*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
953*e1997b9aSAndroid Build Coastguard Worker             },
954*e1997b9aSAndroid Build Coastguard Worker         )
955*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
956*e1997b9aSAndroid Build Coastguard Worker 
957*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
958*e1997b9aSAndroid Build Coastguard Worker 
959*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
960*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
961*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
962*e1997b9aSAndroid Build Coastguard Worker             &source_descriptor,
963*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
964*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
965*e1997b9aSAndroid Build Coastguard Worker             SOURCE_UID,
966*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
967*e1997b9aSAndroid Build Coastguard Worker         )
968*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
969*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
970*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
971*e1997b9aSAndroid Build Coastguard Worker     );
972*e1997b9aSAndroid Build Coastguard Worker 
973*e1997b9aSAndroid Build Coastguard Worker     Ok(())
974*e1997b9aSAndroid Build Coastguard Worker }
975*e1997b9aSAndroid Build Coastguard Worker 
976*e1997b9aSAndroid Build Coastguard Worker // Creates a key migrates it to a different location and then tries to access it by the old
977*e1997b9aSAndroid Build Coastguard Worker // and new location.
978*e1997b9aSAndroid Build Coastguard Worker #[test]
test_migrate_key_app_to_selinux() -> Result<()>979*e1997b9aSAndroid Build Coastguard Worker fn test_migrate_key_app_to_selinux() -> Result<()> {
980*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
981*e1997b9aSAndroid Build Coastguard Worker     const SOURCE_UID: u32 = 1u32;
982*e1997b9aSAndroid Build Coastguard Worker     const DESTINATION_UID: u32 = 2u32;
983*e1997b9aSAndroid Build Coastguard Worker     const DESTINATION_NAMESPACE: i64 = 1000i64;
984*e1997b9aSAndroid Build Coastguard Worker     static SOURCE_ALIAS: &str = "SOURCE_ALIAS";
985*e1997b9aSAndroid Build Coastguard Worker     static DESTINATION_ALIAS: &str = "DESTINATION_ALIAS";
986*e1997b9aSAndroid Build Coastguard Worker     let key_id_guard =
987*e1997b9aSAndroid Build Coastguard Worker         make_test_key_entry(&mut db, Domain::APP, SOURCE_UID as i64, SOURCE_ALIAS, None)
988*e1997b9aSAndroid Build Coastguard Worker             .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?;
989*e1997b9aSAndroid Build Coastguard Worker 
990*e1997b9aSAndroid Build Coastguard Worker     let source_descriptor: KeyDescriptor = KeyDescriptor {
991*e1997b9aSAndroid Build Coastguard Worker         domain: Domain::APP,
992*e1997b9aSAndroid Build Coastguard Worker         nspace: -1,
993*e1997b9aSAndroid Build Coastguard Worker         alias: Some(SOURCE_ALIAS.to_string()),
994*e1997b9aSAndroid Build Coastguard Worker         blob: None,
995*e1997b9aSAndroid Build Coastguard Worker     };
996*e1997b9aSAndroid Build Coastguard Worker 
997*e1997b9aSAndroid Build Coastguard Worker     let destination_descriptor: KeyDescriptor = KeyDescriptor {
998*e1997b9aSAndroid Build Coastguard Worker         domain: Domain::SELINUX,
999*e1997b9aSAndroid Build Coastguard Worker         nspace: DESTINATION_NAMESPACE,
1000*e1997b9aSAndroid Build Coastguard Worker         alias: Some(DESTINATION_ALIAS.to_string()),
1001*e1997b9aSAndroid Build Coastguard Worker         blob: None,
1002*e1997b9aSAndroid Build Coastguard Worker     };
1003*e1997b9aSAndroid Build Coastguard Worker 
1004*e1997b9aSAndroid Build Coastguard Worker     let key_id = key_id_guard.id();
1005*e1997b9aSAndroid Build Coastguard Worker 
1006*e1997b9aSAndroid Build Coastguard Worker     db.migrate_key_namespace(key_id_guard, &destination_descriptor, DESTINATION_UID, |_k| Ok(()))
1007*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1008*e1997b9aSAndroid Build Coastguard Worker 
1009*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
1010*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
1011*e1997b9aSAndroid Build Coastguard Worker             &destination_descriptor,
1012*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1013*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1014*e1997b9aSAndroid Build Coastguard Worker             DESTINATION_UID,
1015*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1016*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::SELINUX, k.domain);
1017*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(DESTINATION_NAMESPACE, k.nspace);
1018*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1019*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1020*e1997b9aSAndroid Build Coastguard Worker             },
1021*e1997b9aSAndroid Build Coastguard Worker         )
1022*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1023*e1997b9aSAndroid Build Coastguard Worker 
1024*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
1025*e1997b9aSAndroid Build Coastguard Worker 
1026*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
1027*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
1028*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
1029*e1997b9aSAndroid Build Coastguard Worker             &source_descriptor,
1030*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1031*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::NONE,
1032*e1997b9aSAndroid Build Coastguard Worker             SOURCE_UID,
1033*e1997b9aSAndroid Build Coastguard Worker             |_k, _av| Ok(()),
1034*e1997b9aSAndroid Build Coastguard Worker         )
1035*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
1036*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
1037*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
1038*e1997b9aSAndroid Build Coastguard Worker     );
1039*e1997b9aSAndroid Build Coastguard Worker 
1040*e1997b9aSAndroid Build Coastguard Worker     Ok(())
1041*e1997b9aSAndroid Build Coastguard Worker }
1042*e1997b9aSAndroid Build Coastguard Worker 
1043*e1997b9aSAndroid Build Coastguard Worker // Creates two keys and tries to migrate the first to the location of the second which
1044*e1997b9aSAndroid Build Coastguard Worker // is expected to fail.
1045*e1997b9aSAndroid Build Coastguard Worker #[test]
test_migrate_key_destination_occupied() -> Result<()>1046*e1997b9aSAndroid Build Coastguard Worker fn test_migrate_key_destination_occupied() -> Result<()> {
1047*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
1048*e1997b9aSAndroid Build Coastguard Worker     const SOURCE_UID: u32 = 1u32;
1049*e1997b9aSAndroid Build Coastguard Worker     const DESTINATION_UID: u32 = 2u32;
1050*e1997b9aSAndroid Build Coastguard Worker     static SOURCE_ALIAS: &str = "SOURCE_ALIAS";
1051*e1997b9aSAndroid Build Coastguard Worker     static DESTINATION_ALIAS: &str = "DESTINATION_ALIAS";
1052*e1997b9aSAndroid Build Coastguard Worker     let key_id_guard =
1053*e1997b9aSAndroid Build Coastguard Worker         make_test_key_entry(&mut db, Domain::APP, SOURCE_UID as i64, SOURCE_ALIAS, None)
1054*e1997b9aSAndroid Build Coastguard Worker             .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?;
1055*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry(&mut db, Domain::APP, DESTINATION_UID as i64, DESTINATION_ALIAS, None)
1056*e1997b9aSAndroid Build Coastguard Worker         .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?;
1057*e1997b9aSAndroid Build Coastguard Worker 
1058*e1997b9aSAndroid Build Coastguard Worker     let destination_descriptor: KeyDescriptor = KeyDescriptor {
1059*e1997b9aSAndroid Build Coastguard Worker         domain: Domain::APP,
1060*e1997b9aSAndroid Build Coastguard Worker         nspace: -1,
1061*e1997b9aSAndroid Build Coastguard Worker         alias: Some(DESTINATION_ALIAS.to_string()),
1062*e1997b9aSAndroid Build Coastguard Worker         blob: None,
1063*e1997b9aSAndroid Build Coastguard Worker     };
1064*e1997b9aSAndroid Build Coastguard Worker 
1065*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
1066*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::INVALID_ARGUMENT)),
1067*e1997b9aSAndroid Build Coastguard Worker         db.migrate_key_namespace(key_id_guard, &destination_descriptor, DESTINATION_UID, |_k| Ok(
1068*e1997b9aSAndroid Build Coastguard Worker             ()
1069*e1997b9aSAndroid Build Coastguard Worker         ))
1070*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
1071*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
1072*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
1073*e1997b9aSAndroid Build Coastguard Worker     );
1074*e1997b9aSAndroid Build Coastguard Worker 
1075*e1997b9aSAndroid Build Coastguard Worker     Ok(())
1076*e1997b9aSAndroid Build Coastguard Worker }
1077*e1997b9aSAndroid Build Coastguard Worker 
1078*e1997b9aSAndroid Build Coastguard Worker #[test]
test_upgrade_0_to_1()1079*e1997b9aSAndroid Build Coastguard Worker fn test_upgrade_0_to_1() {
1080*e1997b9aSAndroid Build Coastguard Worker     const ALIAS1: &str = "test_upgrade_0_to_1_1";
1081*e1997b9aSAndroid Build Coastguard Worker     const ALIAS2: &str = "test_upgrade_0_to_1_2";
1082*e1997b9aSAndroid Build Coastguard Worker     const ALIAS3: &str = "test_upgrade_0_to_1_3";
1083*e1997b9aSAndroid Build Coastguard Worker     const UID: u32 = 33;
1084*e1997b9aSAndroid Build Coastguard Worker     let temp_dir = Arc::new(TempDir::new("test_upgrade_0_to_1").unwrap());
1085*e1997b9aSAndroid Build Coastguard Worker     let mut db = KeystoreDB::new(temp_dir.path(), None).unwrap();
1086*e1997b9aSAndroid Build Coastguard Worker     let key_id_untouched1 =
1087*e1997b9aSAndroid Build Coastguard Worker         make_test_key_entry(&mut db, Domain::APP, UID as i64, ALIAS1, None).unwrap().id();
1088*e1997b9aSAndroid Build Coastguard Worker     let key_id_untouched2 =
1089*e1997b9aSAndroid Build Coastguard Worker         make_bootlevel_key_entry(&mut db, Domain::APP, UID as i64, ALIAS2, false).unwrap().id();
1090*e1997b9aSAndroid Build Coastguard Worker     let key_id_deleted =
1091*e1997b9aSAndroid Build Coastguard Worker         make_bootlevel_key_entry(&mut db, Domain::APP, UID as i64, ALIAS3, true).unwrap().id();
1092*e1997b9aSAndroid Build Coastguard Worker 
1093*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
1094*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
1095*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
1096*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1097*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1098*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(ALIAS1.to_string()),
1099*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1100*e1997b9aSAndroid Build Coastguard Worker             },
1101*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1102*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1103*e1997b9aSAndroid Build Coastguard Worker             UID,
1104*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1105*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
1106*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(UID as i64, k.nspace);
1107*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1108*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1109*e1997b9aSAndroid Build Coastguard Worker             },
1110*e1997b9aSAndroid Build Coastguard Worker         )
1111*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1112*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id_untouched1, None));
1113*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
1114*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
1115*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
1116*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1117*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1118*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(ALIAS2.to_string()),
1119*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1120*e1997b9aSAndroid Build Coastguard Worker             },
1121*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1122*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1123*e1997b9aSAndroid Build Coastguard Worker             UID,
1124*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1125*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
1126*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(UID as i64, k.nspace);
1127*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1128*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1129*e1997b9aSAndroid Build Coastguard Worker             },
1130*e1997b9aSAndroid Build Coastguard Worker         )
1131*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1132*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_bootlevel_test_key_entry_test_vector(key_id_untouched2, false));
1133*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
1134*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
1135*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
1136*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1137*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1138*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(ALIAS3.to_string()),
1139*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1140*e1997b9aSAndroid Build Coastguard Worker             },
1141*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1142*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1143*e1997b9aSAndroid Build Coastguard Worker             UID,
1144*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1145*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
1146*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(UID as i64, k.nspace);
1147*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1148*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1149*e1997b9aSAndroid Build Coastguard Worker             },
1150*e1997b9aSAndroid Build Coastguard Worker         )
1151*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1152*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_bootlevel_test_key_entry_test_vector(key_id_deleted, true));
1153*e1997b9aSAndroid Build Coastguard Worker 
1154*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_test"), |tx| KeystoreDB::from_0_to_1(tx).no_gc()).unwrap();
1155*e1997b9aSAndroid Build Coastguard Worker 
1156*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
1157*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
1158*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
1159*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1160*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1161*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(ALIAS1.to_string()),
1162*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1163*e1997b9aSAndroid Build Coastguard Worker             },
1164*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1165*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1166*e1997b9aSAndroid Build Coastguard Worker             UID,
1167*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1168*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
1169*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(UID as i64, k.nspace);
1170*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1171*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1172*e1997b9aSAndroid Build Coastguard Worker             },
1173*e1997b9aSAndroid Build Coastguard Worker         )
1174*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1175*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_test_key_entry_test_vector(key_id_untouched1, None));
1176*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db
1177*e1997b9aSAndroid Build Coastguard Worker         .load_key_entry(
1178*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
1179*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1180*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1181*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(ALIAS2.to_string()),
1182*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1183*e1997b9aSAndroid Build Coastguard Worker             },
1184*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1185*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1186*e1997b9aSAndroid Build Coastguard Worker             UID,
1187*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1188*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
1189*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(UID as i64, k.nspace);
1190*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1191*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1192*e1997b9aSAndroid Build Coastguard Worker             },
1193*e1997b9aSAndroid Build Coastguard Worker         )
1194*e1997b9aSAndroid Build Coastguard Worker         .unwrap();
1195*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key_entry, make_bootlevel_test_key_entry_test_vector(key_id_untouched2, false));
1196*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
1197*e1997b9aSAndroid Build Coastguard Worker         Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
1198*e1997b9aSAndroid Build Coastguard Worker         db.load_key_entry(
1199*e1997b9aSAndroid Build Coastguard Worker             &KeyDescriptor {
1200*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1201*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1202*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(ALIAS3.to_string()),
1203*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1204*e1997b9aSAndroid Build Coastguard Worker             },
1205*e1997b9aSAndroid Build Coastguard Worker             KeyType::Client,
1206*e1997b9aSAndroid Build Coastguard Worker             KeyEntryLoadBits::BOTH,
1207*e1997b9aSAndroid Build Coastguard Worker             UID,
1208*e1997b9aSAndroid Build Coastguard Worker             |k, av| {
1209*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(Domain::APP, k.domain);
1210*e1997b9aSAndroid Build Coastguard Worker                 assert_eq!(UID as i64, k.nspace);
1211*e1997b9aSAndroid Build Coastguard Worker                 assert!(av.is_none());
1212*e1997b9aSAndroid Build Coastguard Worker                 Ok(())
1213*e1997b9aSAndroid Build Coastguard Worker             },
1214*e1997b9aSAndroid Build Coastguard Worker         )
1215*e1997b9aSAndroid Build Coastguard Worker         .unwrap_err()
1216*e1997b9aSAndroid Build Coastguard Worker         .root_cause()
1217*e1997b9aSAndroid Build Coastguard Worker         .downcast_ref::<KsError>()
1218*e1997b9aSAndroid Build Coastguard Worker     );
1219*e1997b9aSAndroid Build Coastguard Worker }
1220*e1997b9aSAndroid Build Coastguard Worker 
1221*e1997b9aSAndroid Build Coastguard Worker static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
1222*e1997b9aSAndroid Build Coastguard Worker 
1223*e1997b9aSAndroid Build Coastguard Worker #[test]
test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()>1224*e1997b9aSAndroid Build Coastguard Worker fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
1225*e1997b9aSAndroid Build Coastguard Worker     let handle = {
1226*e1997b9aSAndroid Build Coastguard Worker         let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
1227*e1997b9aSAndroid Build Coastguard Worker         let temp_dir_clone = temp_dir.clone();
1228*e1997b9aSAndroid Build Coastguard Worker         let mut db = KeystoreDB::new(temp_dir.path(), None)?;
1229*e1997b9aSAndroid Build Coastguard Worker         let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS, None)
1230*e1997b9aSAndroid Build Coastguard Worker             .context("test_insert_and_load_full_keyentry_domain_app")?
1231*e1997b9aSAndroid Build Coastguard Worker             .0;
1232*e1997b9aSAndroid Build Coastguard Worker         let (_key_guard, key_entry) = db
1233*e1997b9aSAndroid Build Coastguard Worker             .load_key_entry(
1234*e1997b9aSAndroid Build Coastguard Worker                 &KeyDescriptor {
1235*e1997b9aSAndroid Build Coastguard Worker                     domain: Domain::APP,
1236*e1997b9aSAndroid Build Coastguard Worker                     nspace: 0,
1237*e1997b9aSAndroid Build Coastguard Worker                     alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
1238*e1997b9aSAndroid Build Coastguard Worker                     blob: None,
1239*e1997b9aSAndroid Build Coastguard Worker                 },
1240*e1997b9aSAndroid Build Coastguard Worker                 KeyType::Client,
1241*e1997b9aSAndroid Build Coastguard Worker                 KeyEntryLoadBits::BOTH,
1242*e1997b9aSAndroid Build Coastguard Worker                 33,
1243*e1997b9aSAndroid Build Coastguard Worker                 |_k, _av| Ok(()),
1244*e1997b9aSAndroid Build Coastguard Worker             )
1245*e1997b9aSAndroid Build Coastguard Worker             .unwrap();
1246*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
1247*e1997b9aSAndroid Build Coastguard Worker         let state = Arc::new(AtomicU8::new(1));
1248*e1997b9aSAndroid Build Coastguard Worker         let state2 = state.clone();
1249*e1997b9aSAndroid Build Coastguard Worker 
1250*e1997b9aSAndroid Build Coastguard Worker         // Spawning a second thread that attempts to acquire the key id lock
1251*e1997b9aSAndroid Build Coastguard Worker         // for the same key as the primary thread. The primary thread then
1252*e1997b9aSAndroid Build Coastguard Worker         // waits, thereby forcing the secondary thread into the second stage
1253*e1997b9aSAndroid Build Coastguard Worker         // of acquiring the lock (see KEY ID LOCK 2/2 above).
1254*e1997b9aSAndroid Build Coastguard Worker         // The test succeeds if the secondary thread observes the transition
1255*e1997b9aSAndroid Build Coastguard Worker         // of `state` from 1 to 2, despite having a whole second to overtake
1256*e1997b9aSAndroid Build Coastguard Worker         // the primary thread.
1257*e1997b9aSAndroid Build Coastguard Worker         let handle = thread::spawn(move || {
1258*e1997b9aSAndroid Build Coastguard Worker             let temp_dir = temp_dir_clone;
1259*e1997b9aSAndroid Build Coastguard Worker             let mut db = KeystoreDB::new(temp_dir.path(), None).unwrap();
1260*e1997b9aSAndroid Build Coastguard Worker             assert!(db
1261*e1997b9aSAndroid Build Coastguard Worker                 .load_key_entry(
1262*e1997b9aSAndroid Build Coastguard Worker                     &KeyDescriptor {
1263*e1997b9aSAndroid Build Coastguard Worker                         domain: Domain::APP,
1264*e1997b9aSAndroid Build Coastguard Worker                         nspace: 0,
1265*e1997b9aSAndroid Build Coastguard Worker                         alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
1266*e1997b9aSAndroid Build Coastguard Worker                         blob: None,
1267*e1997b9aSAndroid Build Coastguard Worker                     },
1268*e1997b9aSAndroid Build Coastguard Worker                     KeyType::Client,
1269*e1997b9aSAndroid Build Coastguard Worker                     KeyEntryLoadBits::BOTH,
1270*e1997b9aSAndroid Build Coastguard Worker                     33,
1271*e1997b9aSAndroid Build Coastguard Worker                     |_k, _av| Ok(()),
1272*e1997b9aSAndroid Build Coastguard Worker                 )
1273*e1997b9aSAndroid Build Coastguard Worker                 .is_ok());
1274*e1997b9aSAndroid Build Coastguard Worker             // We should only see a 2 here because we can only return
1275*e1997b9aSAndroid Build Coastguard Worker             // from load_key_entry when the `_key_guard` expires,
1276*e1997b9aSAndroid Build Coastguard Worker             // which happens at the end of the scope.
1277*e1997b9aSAndroid Build Coastguard Worker             assert_eq!(2, state2.load(Ordering::Relaxed));
1278*e1997b9aSAndroid Build Coastguard Worker         });
1279*e1997b9aSAndroid Build Coastguard Worker 
1280*e1997b9aSAndroid Build Coastguard Worker         thread::sleep(std::time::Duration::from_millis(1000));
1281*e1997b9aSAndroid Build Coastguard Worker 
1282*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
1283*e1997b9aSAndroid Build Coastguard Worker 
1284*e1997b9aSAndroid Build Coastguard Worker         // Return the handle from this scope so we can join with the
1285*e1997b9aSAndroid Build Coastguard Worker         // secondary thread after the key id lock has expired.
1286*e1997b9aSAndroid Build Coastguard Worker         handle
1287*e1997b9aSAndroid Build Coastguard Worker         // This is where the `_key_guard` goes out of scope,
1288*e1997b9aSAndroid Build Coastguard Worker         // which is the reason for concurrent load_key_entry on the same key
1289*e1997b9aSAndroid Build Coastguard Worker         // to unblock.
1290*e1997b9aSAndroid Build Coastguard Worker     };
1291*e1997b9aSAndroid Build Coastguard Worker     // Join with the secondary thread and unwrap, to propagate failing asserts to the
1292*e1997b9aSAndroid Build Coastguard Worker     // main test thread. We will not see failing asserts in secondary threads otherwise.
1293*e1997b9aSAndroid Build Coastguard Worker     handle.join().unwrap();
1294*e1997b9aSAndroid Build Coastguard Worker     Ok(())
1295*e1997b9aSAndroid Build Coastguard Worker }
1296*e1997b9aSAndroid Build Coastguard Worker 
1297*e1997b9aSAndroid Build Coastguard Worker #[test]
test_database_busy_error_code()1298*e1997b9aSAndroid Build Coastguard Worker fn test_database_busy_error_code() {
1299*e1997b9aSAndroid Build Coastguard Worker     let temp_dir =
1300*e1997b9aSAndroid Build Coastguard Worker         TempDir::new("test_database_busy_error_code_").expect("Failed to create temp dir.");
1301*e1997b9aSAndroid Build Coastguard Worker 
1302*e1997b9aSAndroid Build Coastguard Worker     let mut db1 = KeystoreDB::new(temp_dir.path(), None).expect("Failed to open database1.");
1303*e1997b9aSAndroid Build Coastguard Worker     let mut db2 = KeystoreDB::new(temp_dir.path(), None).expect("Failed to open database2.");
1304*e1997b9aSAndroid Build Coastguard Worker 
1305*e1997b9aSAndroid Build Coastguard Worker     let _tx1 = db1
1306*e1997b9aSAndroid Build Coastguard Worker         .conn
1307*e1997b9aSAndroid Build Coastguard Worker         .transaction_with_behavior(rusqlite::TransactionBehavior::Immediate)
1308*e1997b9aSAndroid Build Coastguard Worker         .expect("Failed to create first transaction.");
1309*e1997b9aSAndroid Build Coastguard Worker 
1310*e1997b9aSAndroid Build Coastguard Worker     let error = db2
1311*e1997b9aSAndroid Build Coastguard Worker         .conn
1312*e1997b9aSAndroid Build Coastguard Worker         .transaction_with_behavior(rusqlite::TransactionBehavior::Immediate)
1313*e1997b9aSAndroid Build Coastguard Worker         .context("Transaction begin failed.")
1314*e1997b9aSAndroid Build Coastguard Worker         .expect_err("This should fail.");
1315*e1997b9aSAndroid Build Coastguard Worker     let root_cause = error.root_cause();
1316*e1997b9aSAndroid Build Coastguard Worker     if let Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseBusy, .. }) =
1317*e1997b9aSAndroid Build Coastguard Worker         root_cause.downcast_ref::<rusqlite::ffi::Error>()
1318*e1997b9aSAndroid Build Coastguard Worker     {
1319*e1997b9aSAndroid Build Coastguard Worker         return;
1320*e1997b9aSAndroid Build Coastguard Worker     }
1321*e1997b9aSAndroid Build Coastguard Worker     panic!(
1322*e1997b9aSAndroid Build Coastguard Worker         "Unexpected error {:?} \n{:?} \n{:?}",
1323*e1997b9aSAndroid Build Coastguard Worker         error,
1324*e1997b9aSAndroid Build Coastguard Worker         root_cause,
1325*e1997b9aSAndroid Build Coastguard Worker         root_cause.downcast_ref::<rusqlite::ffi::Error>()
1326*e1997b9aSAndroid Build Coastguard Worker     )
1327*e1997b9aSAndroid Build Coastguard Worker }
1328*e1997b9aSAndroid Build Coastguard Worker 
1329*e1997b9aSAndroid Build Coastguard Worker #[cfg(disabled)]
1330*e1997b9aSAndroid Build Coastguard Worker #[test]
test_large_number_of_concurrent_db_manipulations() -> Result<()>1331*e1997b9aSAndroid Build Coastguard Worker fn test_large_number_of_concurrent_db_manipulations() -> Result<()> {
1332*e1997b9aSAndroid Build Coastguard Worker     let temp_dir = Arc::new(
1333*e1997b9aSAndroid Build Coastguard Worker         TempDir::new("test_large_number_of_concurrent_db_manipulations_")
1334*e1997b9aSAndroid Build Coastguard Worker             .expect("Failed to create temp dir."),
1335*e1997b9aSAndroid Build Coastguard Worker     );
1336*e1997b9aSAndroid Build Coastguard Worker 
1337*e1997b9aSAndroid Build Coastguard Worker     let test_begin = Instant::now();
1338*e1997b9aSAndroid Build Coastguard Worker 
1339*e1997b9aSAndroid Build Coastguard Worker     const KEY_COUNT: u32 = 500u32;
1340*e1997b9aSAndroid Build Coastguard Worker     let mut db =
1341*e1997b9aSAndroid Build Coastguard Worker         new_test_db_with_gc(temp_dir.path(), |_, _| Ok(())).expect("Failed to open database.");
1342*e1997b9aSAndroid Build Coastguard Worker     const OPEN_DB_COUNT: u32 = 50u32;
1343*e1997b9aSAndroid Build Coastguard Worker 
1344*e1997b9aSAndroid Build Coastguard Worker     let mut actual_key_count = KEY_COUNT;
1345*e1997b9aSAndroid Build Coastguard Worker     // First insert KEY_COUNT keys.
1346*e1997b9aSAndroid Build Coastguard Worker     for count in 0..KEY_COUNT {
1347*e1997b9aSAndroid Build Coastguard Worker         if Instant::now().duration_since(test_begin) >= Duration::from_secs(15) {
1348*e1997b9aSAndroid Build Coastguard Worker             actual_key_count = count;
1349*e1997b9aSAndroid Build Coastguard Worker             break;
1350*e1997b9aSAndroid Build Coastguard Worker         }
1351*e1997b9aSAndroid Build Coastguard Worker         let alias = format!("test_alias_{}", count);
1352*e1997b9aSAndroid Build Coastguard Worker         make_test_key_entry(&mut db, Domain::APP, 1, &alias, None)
1353*e1997b9aSAndroid Build Coastguard Worker             .expect("Failed to make key entry.");
1354*e1997b9aSAndroid Build Coastguard Worker     }
1355*e1997b9aSAndroid Build Coastguard Worker 
1356*e1997b9aSAndroid Build Coastguard Worker     // Insert more keys from a different thread and into a different namespace.
1357*e1997b9aSAndroid Build Coastguard Worker     let temp_dir1 = temp_dir.clone();
1358*e1997b9aSAndroid Build Coastguard Worker     let handle1 = thread::spawn(move || {
1359*e1997b9aSAndroid Build Coastguard Worker         let mut db =
1360*e1997b9aSAndroid Build Coastguard Worker             new_test_db_with_gc(temp_dir1.path(), |_, _| Ok(())).expect("Failed to open database.");
1361*e1997b9aSAndroid Build Coastguard Worker 
1362*e1997b9aSAndroid Build Coastguard Worker         for count in 0..actual_key_count {
1363*e1997b9aSAndroid Build Coastguard Worker             if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
1364*e1997b9aSAndroid Build Coastguard Worker                 return;
1365*e1997b9aSAndroid Build Coastguard Worker             }
1366*e1997b9aSAndroid Build Coastguard Worker             let alias = format!("test_alias_{}", count);
1367*e1997b9aSAndroid Build Coastguard Worker             make_test_key_entry(&mut db, Domain::APP, 2, &alias, None)
1368*e1997b9aSAndroid Build Coastguard Worker                 .expect("Failed to make key entry.");
1369*e1997b9aSAndroid Build Coastguard Worker         }
1370*e1997b9aSAndroid Build Coastguard Worker 
1371*e1997b9aSAndroid Build Coastguard Worker         // then unbind them again.
1372*e1997b9aSAndroid Build Coastguard Worker         for count in 0..actual_key_count {
1373*e1997b9aSAndroid Build Coastguard Worker             if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
1374*e1997b9aSAndroid Build Coastguard Worker                 return;
1375*e1997b9aSAndroid Build Coastguard Worker             }
1376*e1997b9aSAndroid Build Coastguard Worker             let key = KeyDescriptor {
1377*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1378*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1379*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(format!("test_alias_{}", count)),
1380*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1381*e1997b9aSAndroid Build Coastguard Worker             };
1382*e1997b9aSAndroid Build Coastguard Worker             db.unbind_key(&key, KeyType::Client, 2, |_, _| Ok(())).expect("Unbind Failed.");
1383*e1997b9aSAndroid Build Coastguard Worker         }
1384*e1997b9aSAndroid Build Coastguard Worker     });
1385*e1997b9aSAndroid Build Coastguard Worker 
1386*e1997b9aSAndroid Build Coastguard Worker     // And start unbinding the first set of keys.
1387*e1997b9aSAndroid Build Coastguard Worker     let temp_dir2 = temp_dir.clone();
1388*e1997b9aSAndroid Build Coastguard Worker     let handle2 = thread::spawn(move || {
1389*e1997b9aSAndroid Build Coastguard Worker         let mut db =
1390*e1997b9aSAndroid Build Coastguard Worker             new_test_db_with_gc(temp_dir2.path(), |_, _| Ok(())).expect("Failed to open database.");
1391*e1997b9aSAndroid Build Coastguard Worker 
1392*e1997b9aSAndroid Build Coastguard Worker         for count in 0..actual_key_count {
1393*e1997b9aSAndroid Build Coastguard Worker             if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
1394*e1997b9aSAndroid Build Coastguard Worker                 return;
1395*e1997b9aSAndroid Build Coastguard Worker             }
1396*e1997b9aSAndroid Build Coastguard Worker             let key = KeyDescriptor {
1397*e1997b9aSAndroid Build Coastguard Worker                 domain: Domain::APP,
1398*e1997b9aSAndroid Build Coastguard Worker                 nspace: -1,
1399*e1997b9aSAndroid Build Coastguard Worker                 alias: Some(format!("test_alias_{}", count)),
1400*e1997b9aSAndroid Build Coastguard Worker                 blob: None,
1401*e1997b9aSAndroid Build Coastguard Worker             };
1402*e1997b9aSAndroid Build Coastguard Worker             db.unbind_key(&key, KeyType::Client, 1, |_, _| Ok(())).expect("Unbind Failed.");
1403*e1997b9aSAndroid Build Coastguard Worker         }
1404*e1997b9aSAndroid Build Coastguard Worker     });
1405*e1997b9aSAndroid Build Coastguard Worker 
1406*e1997b9aSAndroid Build Coastguard Worker     // While a lot of inserting and deleting is going on we have to open database connections
1407*e1997b9aSAndroid Build Coastguard Worker     // successfully and use them.
1408*e1997b9aSAndroid Build Coastguard Worker     // This clone is not redundant, because temp_dir needs to be kept alive until db goes
1409*e1997b9aSAndroid Build Coastguard Worker     // out of scope.
1410*e1997b9aSAndroid Build Coastguard Worker     #[allow(clippy::redundant_clone)]
1411*e1997b9aSAndroid Build Coastguard Worker     let temp_dir4 = temp_dir.clone();
1412*e1997b9aSAndroid Build Coastguard Worker     let handle4 = thread::spawn(move || {
1413*e1997b9aSAndroid Build Coastguard Worker         for count in 0..OPEN_DB_COUNT {
1414*e1997b9aSAndroid Build Coastguard Worker             if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
1415*e1997b9aSAndroid Build Coastguard Worker                 return;
1416*e1997b9aSAndroid Build Coastguard Worker             }
1417*e1997b9aSAndroid Build Coastguard Worker             let mut db = new_test_db_with_gc(temp_dir4.path(), |_, _| Ok(()))
1418*e1997b9aSAndroid Build Coastguard Worker                 .expect("Failed to open database.");
1419*e1997b9aSAndroid Build Coastguard Worker 
1420*e1997b9aSAndroid Build Coastguard Worker             let alias = format!("test_alias_{}", count);
1421*e1997b9aSAndroid Build Coastguard Worker             make_test_key_entry(&mut db, Domain::APP, 3, &alias, None)
1422*e1997b9aSAndroid Build Coastguard Worker                 .expect("Failed to make key entry.");
1423*e1997b9aSAndroid Build Coastguard Worker             let key =
1424*e1997b9aSAndroid Build Coastguard Worker                 KeyDescriptor { domain: Domain::APP, nspace: -1, alias: Some(alias), blob: None };
1425*e1997b9aSAndroid Build Coastguard Worker             db.unbind_key(&key, KeyType::Client, 3, |_, _| Ok(())).expect("Unbind Failed.");
1426*e1997b9aSAndroid Build Coastguard Worker         }
1427*e1997b9aSAndroid Build Coastguard Worker     });
1428*e1997b9aSAndroid Build Coastguard Worker 
1429*e1997b9aSAndroid Build Coastguard Worker     handle1.join().expect("Thread 1 panicked.");
1430*e1997b9aSAndroid Build Coastguard Worker     handle2.join().expect("Thread 2 panicked.");
1431*e1997b9aSAndroid Build Coastguard Worker     handle4.join().expect("Thread 4 panicked.");
1432*e1997b9aSAndroid Build Coastguard Worker 
1433*e1997b9aSAndroid Build Coastguard Worker     Ok(())
1434*e1997b9aSAndroid Build Coastguard Worker }
1435*e1997b9aSAndroid Build Coastguard Worker 
1436*e1997b9aSAndroid Build Coastguard Worker #[test]
list() -> Result<()>1437*e1997b9aSAndroid Build Coastguard Worker fn list() -> Result<()> {
1438*e1997b9aSAndroid Build Coastguard Worker     let temp_dir = TempDir::new("list_test")?;
1439*e1997b9aSAndroid Build Coastguard Worker     let mut db = KeystoreDB::new(temp_dir.path(), None)?;
1440*e1997b9aSAndroid Build Coastguard Worker     static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
1441*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test1"),
1442*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test2"),
1443*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test3"),
1444*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test4"),
1445*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test5"),
1446*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test6"),
1447*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 1, "test7"),
1448*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test1"),
1449*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test2"),
1450*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test3"),
1451*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test4"),
1452*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test5"),
1453*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test6"),
1454*e1997b9aSAndroid Build Coastguard Worker         (Domain::APP, 2, "test8"),
1455*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test1"),
1456*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test2"),
1457*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test3"),
1458*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test4"),
1459*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test5"),
1460*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test6"),
1461*e1997b9aSAndroid Build Coastguard Worker         (Domain::SELINUX, 100, "test9"),
1462*e1997b9aSAndroid Build Coastguard Worker     ];
1463*e1997b9aSAndroid Build Coastguard Worker 
1464*e1997b9aSAndroid Build Coastguard Worker     let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
1465*e1997b9aSAndroid Build Coastguard Worker         .iter()
1466*e1997b9aSAndroid Build Coastguard Worker         .map(|(domain, ns, alias)| {
1467*e1997b9aSAndroid Build Coastguard Worker             let entry =
1468*e1997b9aSAndroid Build Coastguard Worker                 make_test_key_entry(&mut db, *domain, *ns, alias, None).unwrap_or_else(|e| {
1469*e1997b9aSAndroid Build Coastguard Worker                     panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
1470*e1997b9aSAndroid Build Coastguard Worker                 });
1471*e1997b9aSAndroid Build Coastguard Worker             (entry.id(), *ns)
1472*e1997b9aSAndroid Build Coastguard Worker         })
1473*e1997b9aSAndroid Build Coastguard Worker         .collect();
1474*e1997b9aSAndroid Build Coastguard Worker 
1475*e1997b9aSAndroid Build Coastguard Worker     for (domain, namespace) in
1476*e1997b9aSAndroid Build Coastguard Worker         &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
1477*e1997b9aSAndroid Build Coastguard Worker     {
1478*e1997b9aSAndroid Build Coastguard Worker         let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
1479*e1997b9aSAndroid Build Coastguard Worker             .iter()
1480*e1997b9aSAndroid Build Coastguard Worker             .filter_map(|(domain, ns, alias)| match ns {
1481*e1997b9aSAndroid Build Coastguard Worker                 ns if *ns == *namespace => Some(KeyDescriptor {
1482*e1997b9aSAndroid Build Coastguard Worker                     domain: *domain,
1483*e1997b9aSAndroid Build Coastguard Worker                     nspace: *ns,
1484*e1997b9aSAndroid Build Coastguard Worker                     alias: Some(alias.to_string()),
1485*e1997b9aSAndroid Build Coastguard Worker                     blob: None,
1486*e1997b9aSAndroid Build Coastguard Worker                 }),
1487*e1997b9aSAndroid Build Coastguard Worker                 _ => None,
1488*e1997b9aSAndroid Build Coastguard Worker             })
1489*e1997b9aSAndroid Build Coastguard Worker             .collect();
1490*e1997b9aSAndroid Build Coastguard Worker         list_o_descriptors.sort();
1491*e1997b9aSAndroid Build Coastguard Worker         let mut list_result = db.list_past_alias(*domain, *namespace, KeyType::Client, None)?;
1492*e1997b9aSAndroid Build Coastguard Worker         list_result.sort();
1493*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(list_o_descriptors, list_result);
1494*e1997b9aSAndroid Build Coastguard Worker 
1495*e1997b9aSAndroid Build Coastguard Worker         let mut list_o_ids: Vec<i64> = list_o_descriptors
1496*e1997b9aSAndroid Build Coastguard Worker             .into_iter()
1497*e1997b9aSAndroid Build Coastguard Worker             .map(|d| {
1498*e1997b9aSAndroid Build Coastguard Worker                 let (_, entry) = db
1499*e1997b9aSAndroid Build Coastguard Worker                     .load_key_entry(
1500*e1997b9aSAndroid Build Coastguard Worker                         &d,
1501*e1997b9aSAndroid Build Coastguard Worker                         KeyType::Client,
1502*e1997b9aSAndroid Build Coastguard Worker                         KeyEntryLoadBits::NONE,
1503*e1997b9aSAndroid Build Coastguard Worker                         *namespace as u32,
1504*e1997b9aSAndroid Build Coastguard Worker                         |_, _| Ok(()),
1505*e1997b9aSAndroid Build Coastguard Worker                     )
1506*e1997b9aSAndroid Build Coastguard Worker                     .unwrap();
1507*e1997b9aSAndroid Build Coastguard Worker                 entry.id()
1508*e1997b9aSAndroid Build Coastguard Worker             })
1509*e1997b9aSAndroid Build Coastguard Worker             .collect();
1510*e1997b9aSAndroid Build Coastguard Worker         list_o_ids.sort_unstable();
1511*e1997b9aSAndroid Build Coastguard Worker         let mut loaded_entries: Vec<i64> = list_o_keys
1512*e1997b9aSAndroid Build Coastguard Worker             .iter()
1513*e1997b9aSAndroid Build Coastguard Worker             .filter_map(|(id, ns)| match ns {
1514*e1997b9aSAndroid Build Coastguard Worker                 ns if *ns == *namespace => Some(*id),
1515*e1997b9aSAndroid Build Coastguard Worker                 _ => None,
1516*e1997b9aSAndroid Build Coastguard Worker             })
1517*e1997b9aSAndroid Build Coastguard Worker             .collect();
1518*e1997b9aSAndroid Build Coastguard Worker         loaded_entries.sort_unstable();
1519*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(list_o_ids, loaded_entries);
1520*e1997b9aSAndroid Build Coastguard Worker     }
1521*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(
1522*e1997b9aSAndroid Build Coastguard Worker         Vec::<KeyDescriptor>::new(),
1523*e1997b9aSAndroid Build Coastguard Worker         db.list_past_alias(Domain::SELINUX, 101, KeyType::Client, None)?
1524*e1997b9aSAndroid Build Coastguard Worker     );
1525*e1997b9aSAndroid Build Coastguard Worker 
1526*e1997b9aSAndroid Build Coastguard Worker     Ok(())
1527*e1997b9aSAndroid Build Coastguard Worker }
1528*e1997b9aSAndroid Build Coastguard Worker 
1529*e1997b9aSAndroid Build Coastguard Worker // Helpers
1530*e1997b9aSAndroid Build Coastguard Worker 
1531*e1997b9aSAndroid Build Coastguard Worker // Checks that the given result is an error containing the given string.
check_result_is_error_containing_string<T>(result: Result<T>, target: &str)1532*e1997b9aSAndroid Build Coastguard Worker fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
1533*e1997b9aSAndroid Build Coastguard Worker     let error_str =
1534*e1997b9aSAndroid Build Coastguard Worker         format!("{:#?}", result.err().unwrap_or_else(|| panic!("Expected the error: {}", target)));
1535*e1997b9aSAndroid Build Coastguard Worker     assert!(
1536*e1997b9aSAndroid Build Coastguard Worker         error_str.contains(target),
1537*e1997b9aSAndroid Build Coastguard Worker         "The string \"{}\" should contain \"{}\"",
1538*e1997b9aSAndroid Build Coastguard Worker         error_str,
1539*e1997b9aSAndroid Build Coastguard Worker         target
1540*e1997b9aSAndroid Build Coastguard Worker     );
1541*e1997b9aSAndroid Build Coastguard Worker }
1542*e1997b9aSAndroid Build Coastguard Worker 
1543*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, PartialEq)]
1544*e1997b9aSAndroid Build Coastguard Worker struct KeyEntryRow {
1545*e1997b9aSAndroid Build Coastguard Worker     id: i64,
1546*e1997b9aSAndroid Build Coastguard Worker     key_type: KeyType,
1547*e1997b9aSAndroid Build Coastguard Worker     domain: Option<Domain>,
1548*e1997b9aSAndroid Build Coastguard Worker     namespace: Option<i64>,
1549*e1997b9aSAndroid Build Coastguard Worker     alias: Option<String>,
1550*e1997b9aSAndroid Build Coastguard Worker     state: KeyLifeCycle,
1551*e1997b9aSAndroid Build Coastguard Worker     km_uuid: Option<Uuid>,
1552*e1997b9aSAndroid Build Coastguard Worker }
1553*e1997b9aSAndroid Build Coastguard Worker 
get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>>1554*e1997b9aSAndroid Build Coastguard Worker fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
1555*e1997b9aSAndroid Build Coastguard Worker     db.conn
1556*e1997b9aSAndroid Build Coastguard Worker         .prepare("SELECT * FROM persistent.keyentry;")?
1557*e1997b9aSAndroid Build Coastguard Worker         .query_map([], |row| {
1558*e1997b9aSAndroid Build Coastguard Worker             Ok(KeyEntryRow {
1559*e1997b9aSAndroid Build Coastguard Worker                 id: row.get(0)?,
1560*e1997b9aSAndroid Build Coastguard Worker                 key_type: row.get(1)?,
1561*e1997b9aSAndroid Build Coastguard Worker                 domain: row.get::<_, Option<_>>(2)?.map(Domain),
1562*e1997b9aSAndroid Build Coastguard Worker                 namespace: row.get(3)?,
1563*e1997b9aSAndroid Build Coastguard Worker                 alias: row.get(4)?,
1564*e1997b9aSAndroid Build Coastguard Worker                 state: row.get(5)?,
1565*e1997b9aSAndroid Build Coastguard Worker                 km_uuid: row.get(6)?,
1566*e1997b9aSAndroid Build Coastguard Worker             })
1567*e1997b9aSAndroid Build Coastguard Worker         })?
1568*e1997b9aSAndroid Build Coastguard Worker         .map(|r| r.context("Could not read keyentry row."))
1569*e1997b9aSAndroid Build Coastguard Worker         .collect::<Result<Vec<_>>>()
1570*e1997b9aSAndroid Build Coastguard Worker }
1571*e1997b9aSAndroid Build Coastguard Worker 
make_test_params(max_usage_count: Option<i32>) -> Vec<KeyParameter>1572*e1997b9aSAndroid Build Coastguard Worker fn make_test_params(max_usage_count: Option<i32>) -> Vec<KeyParameter> {
1573*e1997b9aSAndroid Build Coastguard Worker     make_test_params_with_sids(max_usage_count, &[42])
1574*e1997b9aSAndroid Build Coastguard Worker }
1575*e1997b9aSAndroid Build Coastguard Worker 
1576*e1997b9aSAndroid Build Coastguard Worker // Note: The parameters and SecurityLevel associations are nonsensical. This
1577*e1997b9aSAndroid Build Coastguard Worker // collection is only used to check if the parameters are preserved as expected by the
1578*e1997b9aSAndroid Build Coastguard Worker // database.
make_test_params_with_sids( max_usage_count: Option<i32>, user_secure_ids: &[i64], ) -> Vec<KeyParameter>1579*e1997b9aSAndroid Build Coastguard Worker fn make_test_params_with_sids(
1580*e1997b9aSAndroid Build Coastguard Worker     max_usage_count: Option<i32>,
1581*e1997b9aSAndroid Build Coastguard Worker     user_secure_ids: &[i64],
1582*e1997b9aSAndroid Build Coastguard Worker ) -> Vec<KeyParameter> {
1583*e1997b9aSAndroid Build Coastguard Worker     let mut params = vec![
1584*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
1585*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1586*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
1587*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1588*e1997b9aSAndroid Build Coastguard Worker         ),
1589*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1590*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
1591*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1592*e1997b9aSAndroid Build Coastguard Worker         ),
1593*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1594*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::Algorithm(Algorithm::RSA),
1595*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1596*e1997b9aSAndroid Build Coastguard Worker         ),
1597*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
1598*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1599*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::BlockMode(BlockMode::ECB),
1600*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1601*e1997b9aSAndroid Build Coastguard Worker         ),
1602*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1603*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::BlockMode(BlockMode::GCM),
1604*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1605*e1997b9aSAndroid Build Coastguard Worker         ),
1606*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
1607*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1608*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::Digest(Digest::MD5),
1609*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1610*e1997b9aSAndroid Build Coastguard Worker         ),
1611*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1612*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::Digest(Digest::SHA_2_224),
1613*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1614*e1997b9aSAndroid Build Coastguard Worker         ),
1615*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::Digest(Digest::SHA_2_256), SecurityLevel::STRONGBOX),
1616*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1617*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::PaddingMode(PaddingMode::NONE),
1618*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1619*e1997b9aSAndroid Build Coastguard Worker         ),
1620*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1621*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
1622*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1623*e1997b9aSAndroid Build Coastguard Worker         ),
1624*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1625*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
1626*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::STRONGBOX,
1627*e1997b9aSAndroid Build Coastguard Worker         ),
1628*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1629*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
1630*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1631*e1997b9aSAndroid Build Coastguard Worker         ),
1632*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
1633*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
1634*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1635*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::EcCurve(EcCurve::P_224),
1636*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1637*e1997b9aSAndroid Build Coastguard Worker         ),
1638*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
1639*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1640*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::EcCurve(EcCurve::P_384),
1641*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1642*e1997b9aSAndroid Build Coastguard Worker         ),
1643*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1644*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::EcCurve(EcCurve::P_521),
1645*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1646*e1997b9aSAndroid Build Coastguard Worker         ),
1647*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1648*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::RSAPublicExponent(3),
1649*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1650*e1997b9aSAndroid Build Coastguard Worker         ),
1651*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::IncludeUniqueID, SecurityLevel::TRUSTED_ENVIRONMENT),
1652*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
1653*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
1654*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::ActiveDateTime(1234567890), SecurityLevel::STRONGBOX),
1655*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1656*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::OriginationExpireDateTime(1234567890),
1657*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1658*e1997b9aSAndroid Build Coastguard Worker         ),
1659*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1660*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UsageExpireDateTime(1234567890),
1661*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1662*e1997b9aSAndroid Build Coastguard Worker         ),
1663*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1664*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::MinSecondsBetweenOps(1234567890),
1665*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1666*e1997b9aSAndroid Build Coastguard Worker         ),
1667*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1668*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::MaxUsesPerBoot(1234567890),
1669*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1670*e1997b9aSAndroid Build Coastguard Worker         ),
1671*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
1672*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::NoAuthRequired, SecurityLevel::TRUSTED_ENVIRONMENT),
1673*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1674*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
1675*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1676*e1997b9aSAndroid Build Coastguard Worker         ),
1677*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
1678*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
1679*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1680*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::TrustedUserPresenceRequired,
1681*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1682*e1997b9aSAndroid Build Coastguard Worker         ),
1683*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1684*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::TrustedConfirmationRequired,
1685*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1686*e1997b9aSAndroid Build Coastguard Worker         ),
1687*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1688*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UnlockedDeviceRequired,
1689*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1690*e1997b9aSAndroid Build Coastguard Worker         ),
1691*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1692*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
1693*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::SOFTWARE,
1694*e1997b9aSAndroid Build Coastguard Worker         ),
1695*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1696*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
1697*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::SOFTWARE,
1698*e1997b9aSAndroid Build Coastguard Worker         ),
1699*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1700*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::CreationDateTime(12345677890),
1701*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::SOFTWARE,
1702*e1997b9aSAndroid Build Coastguard Worker         ),
1703*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1704*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
1705*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1706*e1997b9aSAndroid Build Coastguard Worker         ),
1707*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1708*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
1709*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1710*e1997b9aSAndroid Build Coastguard Worker         ),
1711*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
1712*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
1713*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1714*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
1715*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::SOFTWARE,
1716*e1997b9aSAndroid Build Coastguard Worker         ),
1717*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1718*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
1719*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1720*e1997b9aSAndroid Build Coastguard Worker         ),
1721*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1722*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
1723*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1724*e1997b9aSAndroid Build Coastguard Worker         ),
1725*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1726*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
1727*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1728*e1997b9aSAndroid Build Coastguard Worker         ),
1729*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1730*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
1731*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1732*e1997b9aSAndroid Build Coastguard Worker         ),
1733*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1734*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
1735*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1736*e1997b9aSAndroid Build Coastguard Worker         ),
1737*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1738*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
1739*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1740*e1997b9aSAndroid Build Coastguard Worker         ),
1741*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1742*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
1743*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1744*e1997b9aSAndroid Build Coastguard Worker         ),
1745*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1746*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdSecondIMEI(vec![4u8, 3u8, 1u8, 2u8]),
1747*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1748*e1997b9aSAndroid Build Coastguard Worker         ),
1749*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1750*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
1751*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1752*e1997b9aSAndroid Build Coastguard Worker         ),
1753*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1754*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
1755*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1756*e1997b9aSAndroid Build Coastguard Worker         ),
1757*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1758*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
1759*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1760*e1997b9aSAndroid Build Coastguard Worker         ),
1761*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1762*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::VendorPatchLevel(3),
1763*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1764*e1997b9aSAndroid Build Coastguard Worker         ),
1765*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::BootPatchLevel(4), SecurityLevel::TRUSTED_ENVIRONMENT),
1766*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1767*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
1768*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1769*e1997b9aSAndroid Build Coastguard Worker         ),
1770*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1771*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
1772*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1773*e1997b9aSAndroid Build Coastguard Worker         ),
1774*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(KeyParameterValue::MacLength(256), SecurityLevel::TRUSTED_ENVIRONMENT),
1775*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1776*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::ResetSinceIdRotation,
1777*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1778*e1997b9aSAndroid Build Coastguard Worker         ),
1779*e1997b9aSAndroid Build Coastguard Worker         KeyParameter::new(
1780*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
1781*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1782*e1997b9aSAndroid Build Coastguard Worker         ),
1783*e1997b9aSAndroid Build Coastguard Worker     ];
1784*e1997b9aSAndroid Build Coastguard Worker     if let Some(value) = max_usage_count {
1785*e1997b9aSAndroid Build Coastguard Worker         params.push(KeyParameter::new(
1786*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UsageCountLimit(value),
1787*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::SOFTWARE,
1788*e1997b9aSAndroid Build Coastguard Worker         ));
1789*e1997b9aSAndroid Build Coastguard Worker     }
1790*e1997b9aSAndroid Build Coastguard Worker 
1791*e1997b9aSAndroid Build Coastguard Worker     for sid in user_secure_ids.iter() {
1792*e1997b9aSAndroid Build Coastguard Worker         params.push(KeyParameter::new(
1793*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UserSecureID(*sid),
1794*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::STRONGBOX,
1795*e1997b9aSAndroid Build Coastguard Worker         ));
1796*e1997b9aSAndroid Build Coastguard Worker     }
1797*e1997b9aSAndroid Build Coastguard Worker     params
1798*e1997b9aSAndroid Build Coastguard Worker }
1799*e1997b9aSAndroid Build Coastguard Worker 
make_test_key_entry( db: &mut KeystoreDB, domain: Domain, namespace: i64, alias: &str, max_usage_count: Option<i32>, ) -> Result<KeyIdGuard>1800*e1997b9aSAndroid Build Coastguard Worker pub fn make_test_key_entry(
1801*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
1802*e1997b9aSAndroid Build Coastguard Worker     domain: Domain,
1803*e1997b9aSAndroid Build Coastguard Worker     namespace: i64,
1804*e1997b9aSAndroid Build Coastguard Worker     alias: &str,
1805*e1997b9aSAndroid Build Coastguard Worker     max_usage_count: Option<i32>,
1806*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> {
1807*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(db, domain, namespace, alias, max_usage_count, &[42])
1808*e1997b9aSAndroid Build Coastguard Worker }
1809*e1997b9aSAndroid Build Coastguard Worker 
make_test_key_entry_with_sids( db: &mut KeystoreDB, domain: Domain, namespace: i64, alias: &str, max_usage_count: Option<i32>, sids: &[i64], ) -> Result<KeyIdGuard>1810*e1997b9aSAndroid Build Coastguard Worker pub fn make_test_key_entry_with_sids(
1811*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
1812*e1997b9aSAndroid Build Coastguard Worker     domain: Domain,
1813*e1997b9aSAndroid Build Coastguard Worker     namespace: i64,
1814*e1997b9aSAndroid Build Coastguard Worker     alias: &str,
1815*e1997b9aSAndroid Build Coastguard Worker     max_usage_count: Option<i32>,
1816*e1997b9aSAndroid Build Coastguard Worker     sids: &[i64],
1817*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> {
1818*e1997b9aSAndroid Build Coastguard Worker     let key_id = create_key_entry(db, &domain, &namespace, KeyType::Client, &KEYSTORE_UUID)?;
1819*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
1820*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password));
1821*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::Salt(vec![1, 2, 3]));
1822*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::Iv(vec![2, 3, 1]));
1823*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::AeadTag(vec![3, 1, 2]));
1824*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID));
1825*e1997b9aSAndroid Build Coastguard Worker 
1826*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB), Some(&blob_metadata))?;
1827*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB), None)?;
1828*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB), None)?;
1829*e1997b9aSAndroid Build Coastguard Worker 
1830*e1997b9aSAndroid Build Coastguard Worker     let params = make_test_params_with_sids(max_usage_count, sids);
1831*e1997b9aSAndroid Build Coastguard Worker     db.insert_keyparameter(&key_id, &params)?;
1832*e1997b9aSAndroid Build Coastguard Worker 
1833*e1997b9aSAndroid Build Coastguard Worker     let mut metadata = KeyMetaData::new();
1834*e1997b9aSAndroid Build Coastguard Worker     metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789)));
1835*e1997b9aSAndroid Build Coastguard Worker     db.insert_key_metadata(&key_id, &metadata)?;
1836*e1997b9aSAndroid Build Coastguard Worker     rebind_alias(db, &key_id, alias, domain, namespace)?;
1837*e1997b9aSAndroid Build Coastguard Worker     Ok(key_id)
1838*e1997b9aSAndroid Build Coastguard Worker }
1839*e1997b9aSAndroid Build Coastguard Worker 
make_test_key_entry_test_vector(key_id: i64, max_usage_count: Option<i32>) -> KeyEntry1840*e1997b9aSAndroid Build Coastguard Worker fn make_test_key_entry_test_vector(key_id: i64, max_usage_count: Option<i32>) -> KeyEntry {
1841*e1997b9aSAndroid Build Coastguard Worker     let params = make_test_params(max_usage_count);
1842*e1997b9aSAndroid Build Coastguard Worker 
1843*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
1844*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password));
1845*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::Salt(vec![1, 2, 3]));
1846*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::Iv(vec![2, 3, 1]));
1847*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::AeadTag(vec![3, 1, 2]));
1848*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID));
1849*e1997b9aSAndroid Build Coastguard Worker 
1850*e1997b9aSAndroid Build Coastguard Worker     let mut metadata = KeyMetaData::new();
1851*e1997b9aSAndroid Build Coastguard Worker     metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789)));
1852*e1997b9aSAndroid Build Coastguard Worker 
1853*e1997b9aSAndroid Build Coastguard Worker     KeyEntry {
1854*e1997b9aSAndroid Build Coastguard Worker         id: key_id,
1855*e1997b9aSAndroid Build Coastguard Worker         key_blob_info: Some((TEST_KEY_BLOB.to_vec(), blob_metadata)),
1856*e1997b9aSAndroid Build Coastguard Worker         cert: Some(TEST_CERT_BLOB.to_vec()),
1857*e1997b9aSAndroid Build Coastguard Worker         cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1858*e1997b9aSAndroid Build Coastguard Worker         km_uuid: KEYSTORE_UUID,
1859*e1997b9aSAndroid Build Coastguard Worker         parameters: params,
1860*e1997b9aSAndroid Build Coastguard Worker         metadata,
1861*e1997b9aSAndroid Build Coastguard Worker         pure_cert: false,
1862*e1997b9aSAndroid Build Coastguard Worker     }
1863*e1997b9aSAndroid Build Coastguard Worker }
1864*e1997b9aSAndroid Build Coastguard Worker 
make_bootlevel_key_entry( db: &mut KeystoreDB, domain: Domain, namespace: i64, alias: &str, logical_only: bool, ) -> Result<KeyIdGuard>1865*e1997b9aSAndroid Build Coastguard Worker pub fn make_bootlevel_key_entry(
1866*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
1867*e1997b9aSAndroid Build Coastguard Worker     domain: Domain,
1868*e1997b9aSAndroid Build Coastguard Worker     namespace: i64,
1869*e1997b9aSAndroid Build Coastguard Worker     alias: &str,
1870*e1997b9aSAndroid Build Coastguard Worker     logical_only: bool,
1871*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> {
1872*e1997b9aSAndroid Build Coastguard Worker     let key_id = create_key_entry(db, &domain, &namespace, KeyType::Client, &KEYSTORE_UUID)?;
1873*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
1874*e1997b9aSAndroid Build Coastguard Worker     if !logical_only {
1875*e1997b9aSAndroid Build Coastguard Worker         blob_metadata.add(BlobMetaEntry::MaxBootLevel(3));
1876*e1997b9aSAndroid Build Coastguard Worker     }
1877*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID));
1878*e1997b9aSAndroid Build Coastguard Worker 
1879*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB), Some(&blob_metadata))?;
1880*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB), None)?;
1881*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB), None)?;
1882*e1997b9aSAndroid Build Coastguard Worker 
1883*e1997b9aSAndroid Build Coastguard Worker     let mut params = make_test_params(None);
1884*e1997b9aSAndroid Build Coastguard Worker     params.push(KeyParameter::new(KeyParameterValue::MaxBootLevel(3), SecurityLevel::KEYSTORE));
1885*e1997b9aSAndroid Build Coastguard Worker 
1886*e1997b9aSAndroid Build Coastguard Worker     db.insert_keyparameter(&key_id, &params)?;
1887*e1997b9aSAndroid Build Coastguard Worker 
1888*e1997b9aSAndroid Build Coastguard Worker     let mut metadata = KeyMetaData::new();
1889*e1997b9aSAndroid Build Coastguard Worker     metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789)));
1890*e1997b9aSAndroid Build Coastguard Worker     db.insert_key_metadata(&key_id, &metadata)?;
1891*e1997b9aSAndroid Build Coastguard Worker     rebind_alias(db, &key_id, alias, domain, namespace)?;
1892*e1997b9aSAndroid Build Coastguard Worker     Ok(key_id)
1893*e1997b9aSAndroid Build Coastguard Worker }
1894*e1997b9aSAndroid Build Coastguard Worker 
1895*e1997b9aSAndroid Build Coastguard Worker // Creates an app key that is marked as being superencrypted by the given
1896*e1997b9aSAndroid Build Coastguard Worker // super key ID and that has the given authentication and unlocked device
1897*e1997b9aSAndroid Build Coastguard Worker // parameters. This does not actually superencrypt the key blob.
make_superencrypted_key_entry( db: &mut KeystoreDB, namespace: i64, alias: &str, requires_authentication: bool, requires_unlocked_device: bool, super_key_id: i64, ) -> Result<KeyIdGuard>1898*e1997b9aSAndroid Build Coastguard Worker fn make_superencrypted_key_entry(
1899*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
1900*e1997b9aSAndroid Build Coastguard Worker     namespace: i64,
1901*e1997b9aSAndroid Build Coastguard Worker     alias: &str,
1902*e1997b9aSAndroid Build Coastguard Worker     requires_authentication: bool,
1903*e1997b9aSAndroid Build Coastguard Worker     requires_unlocked_device: bool,
1904*e1997b9aSAndroid Build Coastguard Worker     super_key_id: i64,
1905*e1997b9aSAndroid Build Coastguard Worker ) -> Result<KeyIdGuard> {
1906*e1997b9aSAndroid Build Coastguard Worker     let domain = Domain::APP;
1907*e1997b9aSAndroid Build Coastguard Worker     let key_id = create_key_entry(db, &domain, &namespace, KeyType::Client, &KEYSTORE_UUID)?;
1908*e1997b9aSAndroid Build Coastguard Worker 
1909*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
1910*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID));
1911*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::KeyId(super_key_id)));
1912*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB), Some(&blob_metadata))?;
1913*e1997b9aSAndroid Build Coastguard Worker 
1914*e1997b9aSAndroid Build Coastguard Worker     let mut params = vec![];
1915*e1997b9aSAndroid Build Coastguard Worker     if requires_unlocked_device {
1916*e1997b9aSAndroid Build Coastguard Worker         params.push(KeyParameter::new(
1917*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UnlockedDeviceRequired,
1918*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1919*e1997b9aSAndroid Build Coastguard Worker         ));
1920*e1997b9aSAndroid Build Coastguard Worker     }
1921*e1997b9aSAndroid Build Coastguard Worker     if requires_authentication {
1922*e1997b9aSAndroid Build Coastguard Worker         params.push(KeyParameter::new(
1923*e1997b9aSAndroid Build Coastguard Worker             KeyParameterValue::UserSecureID(42),
1924*e1997b9aSAndroid Build Coastguard Worker             SecurityLevel::TRUSTED_ENVIRONMENT,
1925*e1997b9aSAndroid Build Coastguard Worker         ));
1926*e1997b9aSAndroid Build Coastguard Worker     }
1927*e1997b9aSAndroid Build Coastguard Worker     db.insert_keyparameter(&key_id, &params)?;
1928*e1997b9aSAndroid Build Coastguard Worker 
1929*e1997b9aSAndroid Build Coastguard Worker     let mut metadata = KeyMetaData::new();
1930*e1997b9aSAndroid Build Coastguard Worker     metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789)));
1931*e1997b9aSAndroid Build Coastguard Worker     db.insert_key_metadata(&key_id, &metadata)?;
1932*e1997b9aSAndroid Build Coastguard Worker 
1933*e1997b9aSAndroid Build Coastguard Worker     rebind_alias(db, &key_id, alias, domain, namespace)?;
1934*e1997b9aSAndroid Build Coastguard Worker     Ok(key_id)
1935*e1997b9aSAndroid Build Coastguard Worker }
1936*e1997b9aSAndroid Build Coastguard Worker 
make_bootlevel_test_key_entry_test_vector(key_id: i64, logical_only: bool) -> KeyEntry1937*e1997b9aSAndroid Build Coastguard Worker fn make_bootlevel_test_key_entry_test_vector(key_id: i64, logical_only: bool) -> KeyEntry {
1938*e1997b9aSAndroid Build Coastguard Worker     let mut params = make_test_params(None);
1939*e1997b9aSAndroid Build Coastguard Worker     params.push(KeyParameter::new(KeyParameterValue::MaxBootLevel(3), SecurityLevel::KEYSTORE));
1940*e1997b9aSAndroid Build Coastguard Worker 
1941*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
1942*e1997b9aSAndroid Build Coastguard Worker     if !logical_only {
1943*e1997b9aSAndroid Build Coastguard Worker         blob_metadata.add(BlobMetaEntry::MaxBootLevel(3));
1944*e1997b9aSAndroid Build Coastguard Worker     }
1945*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::KmUuid(KEYSTORE_UUID));
1946*e1997b9aSAndroid Build Coastguard Worker 
1947*e1997b9aSAndroid Build Coastguard Worker     let mut metadata = KeyMetaData::new();
1948*e1997b9aSAndroid Build Coastguard Worker     metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789)));
1949*e1997b9aSAndroid Build Coastguard Worker 
1950*e1997b9aSAndroid Build Coastguard Worker     KeyEntry {
1951*e1997b9aSAndroid Build Coastguard Worker         id: key_id,
1952*e1997b9aSAndroid Build Coastguard Worker         key_blob_info: Some((TEST_KEY_BLOB.to_vec(), blob_metadata)),
1953*e1997b9aSAndroid Build Coastguard Worker         cert: Some(TEST_CERT_BLOB.to_vec()),
1954*e1997b9aSAndroid Build Coastguard Worker         cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1955*e1997b9aSAndroid Build Coastguard Worker         km_uuid: KEYSTORE_UUID,
1956*e1997b9aSAndroid Build Coastguard Worker         parameters: params,
1957*e1997b9aSAndroid Build Coastguard Worker         metadata,
1958*e1997b9aSAndroid Build Coastguard Worker         pure_cert: false,
1959*e1997b9aSAndroid Build Coastguard Worker     }
1960*e1997b9aSAndroid Build Coastguard Worker }
1961*e1997b9aSAndroid Build Coastguard Worker 
debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()>1962*e1997b9aSAndroid Build Coastguard Worker fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
1963*e1997b9aSAndroid Build Coastguard Worker     let mut stmt = db.conn.prepare(
1964*e1997b9aSAndroid Build Coastguard Worker         "SELECT id, key_type, domain, namespace, alias, state, km_uuid FROM persistent.keyentry;",
1965*e1997b9aSAndroid Build Coastguard Worker     )?;
1966*e1997b9aSAndroid Build Coastguard Worker     let rows =
1967*e1997b9aSAndroid Build Coastguard Worker         stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle, Uuid), _, _>([], |row| {
1968*e1997b9aSAndroid Build Coastguard Worker             Ok((
1969*e1997b9aSAndroid Build Coastguard Worker                 row.get(0)?,
1970*e1997b9aSAndroid Build Coastguard Worker                 row.get(1)?,
1971*e1997b9aSAndroid Build Coastguard Worker                 row.get(2)?,
1972*e1997b9aSAndroid Build Coastguard Worker                 row.get(3)?,
1973*e1997b9aSAndroid Build Coastguard Worker                 row.get(4)?,
1974*e1997b9aSAndroid Build Coastguard Worker                 row.get(5)?,
1975*e1997b9aSAndroid Build Coastguard Worker                 row.get(6)?,
1976*e1997b9aSAndroid Build Coastguard Worker             ))
1977*e1997b9aSAndroid Build Coastguard Worker         })?;
1978*e1997b9aSAndroid Build Coastguard Worker 
1979*e1997b9aSAndroid Build Coastguard Worker     println!("Key entry table rows:");
1980*e1997b9aSAndroid Build Coastguard Worker     for r in rows {
1981*e1997b9aSAndroid Build Coastguard Worker         let (id, key_type, domain, namespace, alias, state, km_uuid) = r.unwrap();
1982*e1997b9aSAndroid Build Coastguard Worker         println!(
1983*e1997b9aSAndroid Build Coastguard Worker             "    id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?} KmUuid: {:?}",
1984*e1997b9aSAndroid Build Coastguard Worker             id, key_type, domain, namespace, alias, state, km_uuid
1985*e1997b9aSAndroid Build Coastguard Worker         );
1986*e1997b9aSAndroid Build Coastguard Worker     }
1987*e1997b9aSAndroid Build Coastguard Worker     Ok(())
1988*e1997b9aSAndroid Build Coastguard Worker }
1989*e1997b9aSAndroid Build Coastguard Worker 
debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()>1990*e1997b9aSAndroid Build Coastguard Worker fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
1991*e1997b9aSAndroid Build Coastguard Worker     let mut stmt =
1992*e1997b9aSAndroid Build Coastguard Worker         db.conn.prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
1993*e1997b9aSAndroid Build Coastguard Worker     let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>([], |row| {
1994*e1997b9aSAndroid Build Coastguard Worker         Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
1995*e1997b9aSAndroid Build Coastguard Worker     })?;
1996*e1997b9aSAndroid Build Coastguard Worker 
1997*e1997b9aSAndroid Build Coastguard Worker     println!("Grant table rows:");
1998*e1997b9aSAndroid Build Coastguard Worker     for r in rows {
1999*e1997b9aSAndroid Build Coastguard Worker         let (id, gt, ki, av) = r.unwrap();
2000*e1997b9aSAndroid Build Coastguard Worker         println!("    id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
2001*e1997b9aSAndroid Build Coastguard Worker     }
2002*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2003*e1997b9aSAndroid Build Coastguard Worker }
2004*e1997b9aSAndroid Build Coastguard Worker 
2005*e1997b9aSAndroid Build Coastguard Worker // Use a custom random number generator that repeats each number once.
2006*e1997b9aSAndroid Build Coastguard Worker // This allows us to test repeated elements.
2007*e1997b9aSAndroid Build Coastguard Worker 
2008*e1997b9aSAndroid Build Coastguard Worker thread_local! {
2009*e1997b9aSAndroid Build Coastguard Worker     static RANDOM_COUNTER: RefCell<i64> = const { RefCell::new(0) };
2010*e1997b9aSAndroid Build Coastguard Worker }
2011*e1997b9aSAndroid Build Coastguard Worker 
reset_random()2012*e1997b9aSAndroid Build Coastguard Worker fn reset_random() {
2013*e1997b9aSAndroid Build Coastguard Worker     RANDOM_COUNTER.with(|counter| {
2014*e1997b9aSAndroid Build Coastguard Worker         *counter.borrow_mut() = 0;
2015*e1997b9aSAndroid Build Coastguard Worker     })
2016*e1997b9aSAndroid Build Coastguard Worker }
2017*e1997b9aSAndroid Build Coastguard Worker 
random() -> i642018*e1997b9aSAndroid Build Coastguard Worker pub fn random() -> i64 {
2019*e1997b9aSAndroid Build Coastguard Worker     RANDOM_COUNTER.with(|counter| {
2020*e1997b9aSAndroid Build Coastguard Worker         let result = *counter.borrow() / 2;
2021*e1997b9aSAndroid Build Coastguard Worker         *counter.borrow_mut() += 1;
2022*e1997b9aSAndroid Build Coastguard Worker         result
2023*e1997b9aSAndroid Build Coastguard Worker     })
2024*e1997b9aSAndroid Build Coastguard Worker }
2025*e1997b9aSAndroid Build Coastguard Worker 
2026*e1997b9aSAndroid Build Coastguard Worker #[test]
test_unbind_keys_for_user() -> Result<()>2027*e1997b9aSAndroid Build Coastguard Worker fn test_unbind_keys_for_user() -> Result<()> {
2028*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2029*e1997b9aSAndroid Build Coastguard Worker     db.unbind_keys_for_user(1)?;
2030*e1997b9aSAndroid Build Coastguard Worker 
2031*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry(&mut db, Domain::APP, 210000, TEST_ALIAS, None)?;
2032*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry(&mut db, Domain::APP, 110000, TEST_ALIAS, None)?;
2033*e1997b9aSAndroid Build Coastguard Worker     db.unbind_keys_for_user(2)?;
2034*e1997b9aSAndroid Build Coastguard Worker 
2035*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(1, db.list_past_alias(Domain::APP, 110000, KeyType::Client, None)?.len());
2036*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, db.list_past_alias(Domain::APP, 210000, KeyType::Client, None)?.len());
2037*e1997b9aSAndroid Build Coastguard Worker 
2038*e1997b9aSAndroid Build Coastguard Worker     db.unbind_keys_for_user(1)?;
2039*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, db.list_past_alias(Domain::APP, 110000, KeyType::Client, None)?.len());
2040*e1997b9aSAndroid Build Coastguard Worker 
2041*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2042*e1997b9aSAndroid Build Coastguard Worker }
2043*e1997b9aSAndroid Build Coastguard Worker 
2044*e1997b9aSAndroid Build Coastguard Worker #[test]
test_unbind_keys_for_user_removes_superkeys() -> Result<()>2045*e1997b9aSAndroid Build Coastguard Worker fn test_unbind_keys_for_user_removes_superkeys() -> Result<()> {
2046*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2047*e1997b9aSAndroid Build Coastguard Worker     let super_key = keystore2_crypto::generate_aes256_key()?;
2048*e1997b9aSAndroid Build Coastguard Worker     let pw: keystore2_crypto::Password = (&b"xyzabc"[..]).into();
2049*e1997b9aSAndroid Build Coastguard Worker     let (encrypted_super_key, metadata) = SuperKeyManager::encrypt_with_password(&super_key, &pw)?;
2050*e1997b9aSAndroid Build Coastguard Worker 
2051*e1997b9aSAndroid Build Coastguard Worker     let key_name_enc = SuperKeyType {
2052*e1997b9aSAndroid Build Coastguard Worker         alias: "test_super_key_1",
2053*e1997b9aSAndroid Build Coastguard Worker         algorithm: SuperEncryptionAlgorithm::Aes256Gcm,
2054*e1997b9aSAndroid Build Coastguard Worker         name: "test_super_key_1",
2055*e1997b9aSAndroid Build Coastguard Worker     };
2056*e1997b9aSAndroid Build Coastguard Worker 
2057*e1997b9aSAndroid Build Coastguard Worker     let key_name_nonenc = SuperKeyType {
2058*e1997b9aSAndroid Build Coastguard Worker         alias: "test_super_key_2",
2059*e1997b9aSAndroid Build Coastguard Worker         algorithm: SuperEncryptionAlgorithm::Aes256Gcm,
2060*e1997b9aSAndroid Build Coastguard Worker         name: "test_super_key_2",
2061*e1997b9aSAndroid Build Coastguard Worker     };
2062*e1997b9aSAndroid Build Coastguard Worker 
2063*e1997b9aSAndroid Build Coastguard Worker     // Install two super keys.
2064*e1997b9aSAndroid Build Coastguard Worker     db.store_super_key(1, &key_name_nonenc, &super_key, &BlobMetaData::new(), &KeyMetaData::new())?;
2065*e1997b9aSAndroid Build Coastguard Worker     db.store_super_key(1, &key_name_enc, &encrypted_super_key, &metadata, &KeyMetaData::new())?;
2066*e1997b9aSAndroid Build Coastguard Worker 
2067*e1997b9aSAndroid Build Coastguard Worker     // Check that both can be found in the database.
2068*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_enc, 1)?.is_some());
2069*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_nonenc, 1)?.is_some());
2070*e1997b9aSAndroid Build Coastguard Worker 
2071*e1997b9aSAndroid Build Coastguard Worker     // Install the same keys for a different user.
2072*e1997b9aSAndroid Build Coastguard Worker     db.store_super_key(2, &key_name_nonenc, &super_key, &BlobMetaData::new(), &KeyMetaData::new())?;
2073*e1997b9aSAndroid Build Coastguard Worker     db.store_super_key(2, &key_name_enc, &encrypted_super_key, &metadata, &KeyMetaData::new())?;
2074*e1997b9aSAndroid Build Coastguard Worker 
2075*e1997b9aSAndroid Build Coastguard Worker     // Check that the second pair of keys can be found in the database.
2076*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_enc, 2)?.is_some());
2077*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_nonenc, 2)?.is_some());
2078*e1997b9aSAndroid Build Coastguard Worker 
2079*e1997b9aSAndroid Build Coastguard Worker     // Delete all keys for user 1.
2080*e1997b9aSAndroid Build Coastguard Worker     db.unbind_keys_for_user(1)?;
2081*e1997b9aSAndroid Build Coastguard Worker 
2082*e1997b9aSAndroid Build Coastguard Worker     // All of user 1's keys should be gone.
2083*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_enc, 1)?.is_none());
2084*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_nonenc, 1)?.is_none());
2085*e1997b9aSAndroid Build Coastguard Worker 
2086*e1997b9aSAndroid Build Coastguard Worker     // User 2's keys should not have been touched.
2087*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_enc, 2)?.is_some());
2088*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(&key_name_nonenc, 2)?.is_some());
2089*e1997b9aSAndroid Build Coastguard Worker 
2090*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2091*e1997b9aSAndroid Build Coastguard Worker }
2092*e1997b9aSAndroid Build Coastguard Worker 
app_key_exists(db: &mut KeystoreDB, nspace: i64, alias: &str) -> Result<bool>2093*e1997b9aSAndroid Build Coastguard Worker fn app_key_exists(db: &mut KeystoreDB, nspace: i64, alias: &str) -> Result<bool> {
2094*e1997b9aSAndroid Build Coastguard Worker     db.key_exists(Domain::APP, nspace, alias, KeyType::Client)
2095*e1997b9aSAndroid Build Coastguard Worker }
2096*e1997b9aSAndroid Build Coastguard Worker 
2097*e1997b9aSAndroid Build Coastguard Worker // Tests the unbind_auth_bound_keys_for_user() function.
2098*e1997b9aSAndroid Build Coastguard Worker #[test]
test_unbind_auth_bound_keys_for_user() -> Result<()>2099*e1997b9aSAndroid Build Coastguard Worker fn test_unbind_auth_bound_keys_for_user() -> Result<()> {
2100*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2101*e1997b9aSAndroid Build Coastguard Worker     let user_id = 1;
2102*e1997b9aSAndroid Build Coastguard Worker     let nspace: i64 = (user_id * AID_USER_OFFSET).into();
2103*e1997b9aSAndroid Build Coastguard Worker     let other_user_id = 2;
2104*e1997b9aSAndroid Build Coastguard Worker     let other_user_nspace: i64 = (other_user_id * AID_USER_OFFSET).into();
2105*e1997b9aSAndroid Build Coastguard Worker     let super_key_type = &USER_AFTER_FIRST_UNLOCK_SUPER_KEY;
2106*e1997b9aSAndroid Build Coastguard Worker 
2107*e1997b9aSAndroid Build Coastguard Worker     // Create a superencryption key.
2108*e1997b9aSAndroid Build Coastguard Worker     let super_key = keystore2_crypto::generate_aes256_key()?;
2109*e1997b9aSAndroid Build Coastguard Worker     let pw: keystore2_crypto::Password = (&b"xyzabc"[..]).into();
2110*e1997b9aSAndroid Build Coastguard Worker     let (encrypted_super_key, blob_metadata) =
2111*e1997b9aSAndroid Build Coastguard Worker         SuperKeyManager::encrypt_with_password(&super_key, &pw)?;
2112*e1997b9aSAndroid Build Coastguard Worker     db.store_super_key(
2113*e1997b9aSAndroid Build Coastguard Worker         user_id,
2114*e1997b9aSAndroid Build Coastguard Worker         super_key_type,
2115*e1997b9aSAndroid Build Coastguard Worker         &encrypted_super_key,
2116*e1997b9aSAndroid Build Coastguard Worker         &blob_metadata,
2117*e1997b9aSAndroid Build Coastguard Worker         &KeyMetaData::new(),
2118*e1997b9aSAndroid Build Coastguard Worker     )?;
2119*e1997b9aSAndroid Build Coastguard Worker     let super_key_id = db.load_super_key(super_key_type, user_id)?.unwrap().0 .0;
2120*e1997b9aSAndroid Build Coastguard Worker 
2121*e1997b9aSAndroid Build Coastguard Worker     // Store 4 superencrypted app keys, one for each possible combination of
2122*e1997b9aSAndroid Build Coastguard Worker     // (authentication required, unlocked device required).
2123*e1997b9aSAndroid Build Coastguard Worker     make_superencrypted_key_entry(&mut db, nspace, "noauth_noud", false, false, super_key_id)?;
2124*e1997b9aSAndroid Build Coastguard Worker     make_superencrypted_key_entry(&mut db, nspace, "noauth_ud", false, true, super_key_id)?;
2125*e1997b9aSAndroid Build Coastguard Worker     make_superencrypted_key_entry(&mut db, nspace, "auth_noud", true, false, super_key_id)?;
2126*e1997b9aSAndroid Build Coastguard Worker     make_superencrypted_key_entry(&mut db, nspace, "auth_ud", true, true, super_key_id)?;
2127*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, nspace, "noauth_noud")?);
2128*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, nspace, "noauth_ud")?);
2129*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, nspace, "auth_noud")?);
2130*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, nspace, "auth_ud")?);
2131*e1997b9aSAndroid Build Coastguard Worker 
2132*e1997b9aSAndroid Build Coastguard Worker     // Also store a key for a different user that requires authentication.
2133*e1997b9aSAndroid Build Coastguard Worker     make_superencrypted_key_entry(&mut db, other_user_nspace, "auth_ud", true, true, super_key_id)?;
2134*e1997b9aSAndroid Build Coastguard Worker 
2135*e1997b9aSAndroid Build Coastguard Worker     db.unbind_auth_bound_keys_for_user(user_id)?;
2136*e1997b9aSAndroid Build Coastguard Worker 
2137*e1997b9aSAndroid Build Coastguard Worker     // Verify that only the user's app keys that require authentication were
2138*e1997b9aSAndroid Build Coastguard Worker     // deleted. Keys that require an unlocked device but not authentication
2139*e1997b9aSAndroid Build Coastguard Worker     // should *not* have been deleted, nor should the super key have been
2140*e1997b9aSAndroid Build Coastguard Worker     // deleted, nor should other users' keys have been deleted.
2141*e1997b9aSAndroid Build Coastguard Worker     assert!(db.load_super_key(super_key_type, user_id)?.is_some());
2142*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, nspace, "noauth_noud")?);
2143*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, nspace, "noauth_ud")?);
2144*e1997b9aSAndroid Build Coastguard Worker     assert!(!app_key_exists(&mut db, nspace, "auth_noud")?);
2145*e1997b9aSAndroid Build Coastguard Worker     assert!(!app_key_exists(&mut db, nspace, "auth_ud")?);
2146*e1997b9aSAndroid Build Coastguard Worker     assert!(app_key_exists(&mut db, other_user_nspace, "auth_ud")?);
2147*e1997b9aSAndroid Build Coastguard Worker 
2148*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2149*e1997b9aSAndroid Build Coastguard Worker }
2150*e1997b9aSAndroid Build Coastguard Worker 
2151*e1997b9aSAndroid Build Coastguard Worker #[test]
test_store_super_key() -> Result<()>2152*e1997b9aSAndroid Build Coastguard Worker fn test_store_super_key() -> Result<()> {
2153*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2154*e1997b9aSAndroid Build Coastguard Worker     let pw: keystore2_crypto::Password = (&b"xyzabc"[..]).into();
2155*e1997b9aSAndroid Build Coastguard Worker     let super_key = keystore2_crypto::generate_aes256_key()?;
2156*e1997b9aSAndroid Build Coastguard Worker     let secret_bytes = b"keystore2 is great.";
2157*e1997b9aSAndroid Build Coastguard Worker     let (encrypted_secret, iv, tag) = keystore2_crypto::aes_gcm_encrypt(secret_bytes, &super_key)?;
2158*e1997b9aSAndroid Build Coastguard Worker 
2159*e1997b9aSAndroid Build Coastguard Worker     let (encrypted_super_key, metadata) = SuperKeyManager::encrypt_with_password(&super_key, &pw)?;
2160*e1997b9aSAndroid Build Coastguard Worker     db.store_super_key(
2161*e1997b9aSAndroid Build Coastguard Worker         1,
2162*e1997b9aSAndroid Build Coastguard Worker         &USER_AFTER_FIRST_UNLOCK_SUPER_KEY,
2163*e1997b9aSAndroid Build Coastguard Worker         &encrypted_super_key,
2164*e1997b9aSAndroid Build Coastguard Worker         &metadata,
2165*e1997b9aSAndroid Build Coastguard Worker         &KeyMetaData::new(),
2166*e1997b9aSAndroid Build Coastguard Worker     )?;
2167*e1997b9aSAndroid Build Coastguard Worker 
2168*e1997b9aSAndroid Build Coastguard Worker     // Check if super key exists.
2169*e1997b9aSAndroid Build Coastguard Worker     assert!(db.key_exists(
2170*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2171*e1997b9aSAndroid Build Coastguard Worker         1,
2172*e1997b9aSAndroid Build Coastguard Worker         USER_AFTER_FIRST_UNLOCK_SUPER_KEY.alias,
2173*e1997b9aSAndroid Build Coastguard Worker         KeyType::Super
2174*e1997b9aSAndroid Build Coastguard Worker     )?);
2175*e1997b9aSAndroid Build Coastguard Worker 
2176*e1997b9aSAndroid Build Coastguard Worker     let (_, key_entry) = db.load_super_key(&USER_AFTER_FIRST_UNLOCK_SUPER_KEY, 1)?.unwrap();
2177*e1997b9aSAndroid Build Coastguard Worker     let loaded_super_key = SuperKeyManager::extract_super_key_from_key_entry(
2178*e1997b9aSAndroid Build Coastguard Worker         USER_AFTER_FIRST_UNLOCK_SUPER_KEY.algorithm,
2179*e1997b9aSAndroid Build Coastguard Worker         key_entry,
2180*e1997b9aSAndroid Build Coastguard Worker         &pw,
2181*e1997b9aSAndroid Build Coastguard Worker         None,
2182*e1997b9aSAndroid Build Coastguard Worker     )?;
2183*e1997b9aSAndroid Build Coastguard Worker 
2184*e1997b9aSAndroid Build Coastguard Worker     let decrypted_secret_bytes = loaded_super_key.decrypt(&encrypted_secret, &iv, &tag)?;
2185*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(secret_bytes, &*decrypted_secret_bytes);
2186*e1997b9aSAndroid Build Coastguard Worker 
2187*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2188*e1997b9aSAndroid Build Coastguard Worker }
2189*e1997b9aSAndroid Build Coastguard Worker 
get_valid_statsd_storage_types() -> Vec<MetricsStorage>2190*e1997b9aSAndroid Build Coastguard Worker fn get_valid_statsd_storage_types() -> Vec<MetricsStorage> {
2191*e1997b9aSAndroid Build Coastguard Worker     vec![
2192*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_ENTRY,
2193*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_ENTRY_ID_INDEX,
2194*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX,
2195*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::BLOB_ENTRY,
2196*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX,
2197*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_PARAMETER,
2198*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX,
2199*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_METADATA,
2200*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX,
2201*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::GRANT,
2202*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::AUTH_TOKEN,
2203*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::BLOB_METADATA,
2204*e1997b9aSAndroid Build Coastguard Worker         MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX,
2205*e1997b9aSAndroid Build Coastguard Worker     ]
2206*e1997b9aSAndroid Build Coastguard Worker }
2207*e1997b9aSAndroid Build Coastguard Worker 
2208*e1997b9aSAndroid Build Coastguard Worker /// Perform a simple check to ensure that we can query all the storage types
2209*e1997b9aSAndroid Build Coastguard Worker /// that are supported by the DB. Check for reasonable values.
2210*e1997b9aSAndroid Build Coastguard Worker #[test]
test_query_all_valid_table_sizes() -> Result<()>2211*e1997b9aSAndroid Build Coastguard Worker fn test_query_all_valid_table_sizes() -> Result<()> {
2212*e1997b9aSAndroid Build Coastguard Worker     const PAGE_SIZE: i32 = 4096;
2213*e1997b9aSAndroid Build Coastguard Worker 
2214*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2215*e1997b9aSAndroid Build Coastguard Worker 
2216*e1997b9aSAndroid Build Coastguard Worker     for t in get_valid_statsd_storage_types() {
2217*e1997b9aSAndroid Build Coastguard Worker         let stat = db.get_storage_stat(t)?;
2218*e1997b9aSAndroid Build Coastguard Worker         // AuthToken can be less than a page since it's in a btree, not sqlite
2219*e1997b9aSAndroid Build Coastguard Worker         // TODO(b/187474736) stop using if-let here
2220*e1997b9aSAndroid Build Coastguard Worker         if let MetricsStorage::AUTH_TOKEN = t {
2221*e1997b9aSAndroid Build Coastguard Worker         } else {
2222*e1997b9aSAndroid Build Coastguard Worker             assert!(stat.size >= PAGE_SIZE);
2223*e1997b9aSAndroid Build Coastguard Worker         }
2224*e1997b9aSAndroid Build Coastguard Worker         assert!(stat.size >= stat.unused_size);
2225*e1997b9aSAndroid Build Coastguard Worker     }
2226*e1997b9aSAndroid Build Coastguard Worker 
2227*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2228*e1997b9aSAndroid Build Coastguard Worker }
2229*e1997b9aSAndroid Build Coastguard Worker 
get_storage_stats_map(db: &mut KeystoreDB) -> BTreeMap<i32, StorageStats>2230*e1997b9aSAndroid Build Coastguard Worker fn get_storage_stats_map(db: &mut KeystoreDB) -> BTreeMap<i32, StorageStats> {
2231*e1997b9aSAndroid Build Coastguard Worker     get_valid_statsd_storage_types()
2232*e1997b9aSAndroid Build Coastguard Worker         .into_iter()
2233*e1997b9aSAndroid Build Coastguard Worker         .map(|t| (t.0, db.get_storage_stat(t).unwrap()))
2234*e1997b9aSAndroid Build Coastguard Worker         .collect()
2235*e1997b9aSAndroid Build Coastguard Worker }
2236*e1997b9aSAndroid Build Coastguard Worker 
assert_storage_increased( db: &mut KeystoreDB, increased_storage_types: Vec<MetricsStorage>, baseline: &mut BTreeMap<i32, StorageStats>, )2237*e1997b9aSAndroid Build Coastguard Worker fn assert_storage_increased(
2238*e1997b9aSAndroid Build Coastguard Worker     db: &mut KeystoreDB,
2239*e1997b9aSAndroid Build Coastguard Worker     increased_storage_types: Vec<MetricsStorage>,
2240*e1997b9aSAndroid Build Coastguard Worker     baseline: &mut BTreeMap<i32, StorageStats>,
2241*e1997b9aSAndroid Build Coastguard Worker ) {
2242*e1997b9aSAndroid Build Coastguard Worker     for storage in increased_storage_types {
2243*e1997b9aSAndroid Build Coastguard Worker         // Verify the expected storage increased.
2244*e1997b9aSAndroid Build Coastguard Worker         let new = db.get_storage_stat(storage).unwrap();
2245*e1997b9aSAndroid Build Coastguard Worker         let old = &baseline[&storage.0];
2246*e1997b9aSAndroid Build Coastguard Worker         assert!(new.size >= old.size, "{}: {} >= {}", storage.0, new.size, old.size);
2247*e1997b9aSAndroid Build Coastguard Worker         assert!(
2248*e1997b9aSAndroid Build Coastguard Worker             new.unused_size <= old.unused_size,
2249*e1997b9aSAndroid Build Coastguard Worker             "{}: {} <= {}",
2250*e1997b9aSAndroid Build Coastguard Worker             storage.0,
2251*e1997b9aSAndroid Build Coastguard Worker             new.unused_size,
2252*e1997b9aSAndroid Build Coastguard Worker             old.unused_size
2253*e1997b9aSAndroid Build Coastguard Worker         );
2254*e1997b9aSAndroid Build Coastguard Worker 
2255*e1997b9aSAndroid Build Coastguard Worker         // Update the baseline with the new value so that it succeeds in the
2256*e1997b9aSAndroid Build Coastguard Worker         // later comparison.
2257*e1997b9aSAndroid Build Coastguard Worker         baseline.insert(storage.0, new);
2258*e1997b9aSAndroid Build Coastguard Worker     }
2259*e1997b9aSAndroid Build Coastguard Worker 
2260*e1997b9aSAndroid Build Coastguard Worker     // Get an updated map of the storage and verify there were no unexpected changes.
2261*e1997b9aSAndroid Build Coastguard Worker     let updated_stats = get_storage_stats_map(db);
2262*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(updated_stats.len(), baseline.len());
2263*e1997b9aSAndroid Build Coastguard Worker 
2264*e1997b9aSAndroid Build Coastguard Worker     for &k in baseline.keys() {
2265*e1997b9aSAndroid Build Coastguard Worker         let stringify = |map: &BTreeMap<i32, StorageStats>| -> String {
2266*e1997b9aSAndroid Build Coastguard Worker             let mut s = String::new();
2267*e1997b9aSAndroid Build Coastguard Worker             for &k in map.keys() {
2268*e1997b9aSAndroid Build Coastguard Worker                 writeln!(&mut s, "  {}: {}, {}", &k, map[&k].size, map[&k].unused_size)
2269*e1997b9aSAndroid Build Coastguard Worker                     .expect("string concat failed");
2270*e1997b9aSAndroid Build Coastguard Worker             }
2271*e1997b9aSAndroid Build Coastguard Worker             s
2272*e1997b9aSAndroid Build Coastguard Worker         };
2273*e1997b9aSAndroid Build Coastguard Worker 
2274*e1997b9aSAndroid Build Coastguard Worker         assert!(
2275*e1997b9aSAndroid Build Coastguard Worker             updated_stats[&k].size == baseline[&k].size
2276*e1997b9aSAndroid Build Coastguard Worker                 && updated_stats[&k].unused_size == baseline[&k].unused_size,
2277*e1997b9aSAndroid Build Coastguard Worker             "updated_stats:\n{}\nbaseline:\n{}",
2278*e1997b9aSAndroid Build Coastguard Worker             stringify(&updated_stats),
2279*e1997b9aSAndroid Build Coastguard Worker             stringify(baseline)
2280*e1997b9aSAndroid Build Coastguard Worker         );
2281*e1997b9aSAndroid Build Coastguard Worker     }
2282*e1997b9aSAndroid Build Coastguard Worker }
2283*e1997b9aSAndroid Build Coastguard Worker 
2284*e1997b9aSAndroid Build Coastguard Worker #[test]
test_verify_key_table_size_reporting() -> Result<()>2285*e1997b9aSAndroid Build Coastguard Worker fn test_verify_key_table_size_reporting() -> Result<()> {
2286*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2287*e1997b9aSAndroid Build Coastguard Worker     let mut working_stats = get_storage_stats_map(&mut db);
2288*e1997b9aSAndroid Build Coastguard Worker 
2289*e1997b9aSAndroid Build Coastguard Worker     let key_id = create_key_entry(&mut db, &Domain::APP, &42, KeyType::Client, &KEYSTORE_UUID)?;
2290*e1997b9aSAndroid Build Coastguard Worker     assert_storage_increased(
2291*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2292*e1997b9aSAndroid Build Coastguard Worker         vec![
2293*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::KEY_ENTRY,
2294*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::KEY_ENTRY_ID_INDEX,
2295*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX,
2296*e1997b9aSAndroid Build Coastguard Worker         ],
2297*e1997b9aSAndroid Build Coastguard Worker         &mut working_stats,
2298*e1997b9aSAndroid Build Coastguard Worker     );
2299*e1997b9aSAndroid Build Coastguard Worker 
2300*e1997b9aSAndroid Build Coastguard Worker     let mut blob_metadata = BlobMetaData::new();
2301*e1997b9aSAndroid Build Coastguard Worker     blob_metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password));
2302*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB), None)?;
2303*e1997b9aSAndroid Build Coastguard Worker     assert_storage_increased(
2304*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2305*e1997b9aSAndroid Build Coastguard Worker         vec![
2306*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::BLOB_ENTRY,
2307*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX,
2308*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::BLOB_METADATA,
2309*e1997b9aSAndroid Build Coastguard Worker             MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX,
2310*e1997b9aSAndroid Build Coastguard Worker         ],
2311*e1997b9aSAndroid Build Coastguard Worker         &mut working_stats,
2312*e1997b9aSAndroid Build Coastguard Worker     );
2313*e1997b9aSAndroid Build Coastguard Worker 
2314*e1997b9aSAndroid Build Coastguard Worker     let params = make_test_params(None);
2315*e1997b9aSAndroid Build Coastguard Worker     db.insert_keyparameter(&key_id, &params)?;
2316*e1997b9aSAndroid Build Coastguard Worker     assert_storage_increased(
2317*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2318*e1997b9aSAndroid Build Coastguard Worker         vec![MetricsStorage::KEY_PARAMETER, MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX],
2319*e1997b9aSAndroid Build Coastguard Worker         &mut working_stats,
2320*e1997b9aSAndroid Build Coastguard Worker     );
2321*e1997b9aSAndroid Build Coastguard Worker 
2322*e1997b9aSAndroid Build Coastguard Worker     let mut metadata = KeyMetaData::new();
2323*e1997b9aSAndroid Build Coastguard Worker     metadata.add(KeyMetaEntry::CreationDate(DateTime::from_millis_epoch(123456789)));
2324*e1997b9aSAndroid Build Coastguard Worker     db.insert_key_metadata(&key_id, &metadata)?;
2325*e1997b9aSAndroid Build Coastguard Worker     assert_storage_increased(
2326*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2327*e1997b9aSAndroid Build Coastguard Worker         vec![MetricsStorage::KEY_METADATA, MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX],
2328*e1997b9aSAndroid Build Coastguard Worker         &mut working_stats,
2329*e1997b9aSAndroid Build Coastguard Worker     );
2330*e1997b9aSAndroid Build Coastguard Worker 
2331*e1997b9aSAndroid Build Coastguard Worker     let mut sum = 0;
2332*e1997b9aSAndroid Build Coastguard Worker     for stat in working_stats.values() {
2333*e1997b9aSAndroid Build Coastguard Worker         sum += stat.size;
2334*e1997b9aSAndroid Build Coastguard Worker     }
2335*e1997b9aSAndroid Build Coastguard Worker     let total = db.get_storage_stat(MetricsStorage::DATABASE)?.size;
2336*e1997b9aSAndroid Build Coastguard Worker     assert!(sum <= total, "Expected sum <= total. sum: {}, total: {}", sum, total);
2337*e1997b9aSAndroid Build Coastguard Worker 
2338*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2339*e1997b9aSAndroid Build Coastguard Worker }
2340*e1997b9aSAndroid Build Coastguard Worker 
2341*e1997b9aSAndroid Build Coastguard Worker #[test]
test_verify_auth_table_size_reporting() -> Result<()>2342*e1997b9aSAndroid Build Coastguard Worker fn test_verify_auth_table_size_reporting() -> Result<()> {
2343*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2344*e1997b9aSAndroid Build Coastguard Worker     let mut working_stats = get_storage_stats_map(&mut db);
2345*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&HardwareAuthToken {
2346*e1997b9aSAndroid Build Coastguard Worker         challenge: 123,
2347*e1997b9aSAndroid Build Coastguard Worker         userId: 456,
2348*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 789,
2349*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type::ANY,
2350*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 10 },
2351*e1997b9aSAndroid Build Coastguard Worker         mac: b"mac".to_vec(),
2352*e1997b9aSAndroid Build Coastguard Worker     });
2353*e1997b9aSAndroid Build Coastguard Worker     assert_storage_increased(&mut db, vec![MetricsStorage::AUTH_TOKEN], &mut working_stats);
2354*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2355*e1997b9aSAndroid Build Coastguard Worker }
2356*e1997b9aSAndroid Build Coastguard Worker 
2357*e1997b9aSAndroid Build Coastguard Worker #[test]
test_verify_grant_table_size_reporting() -> Result<()>2358*e1997b9aSAndroid Build Coastguard Worker fn test_verify_grant_table_size_reporting() -> Result<()> {
2359*e1997b9aSAndroid Build Coastguard Worker     const OWNER: i64 = 1;
2360*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2361*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry(&mut db, Domain::APP, OWNER, TEST_ALIAS, None)?;
2362*e1997b9aSAndroid Build Coastguard Worker 
2363*e1997b9aSAndroid Build Coastguard Worker     let mut working_stats = get_storage_stats_map(&mut db);
2364*e1997b9aSAndroid Build Coastguard Worker     db.grant(
2365*e1997b9aSAndroid Build Coastguard Worker         &KeyDescriptor {
2366*e1997b9aSAndroid Build Coastguard Worker             domain: Domain::APP,
2367*e1997b9aSAndroid Build Coastguard Worker             nspace: 0,
2368*e1997b9aSAndroid Build Coastguard Worker             alias: Some(TEST_ALIAS.to_string()),
2369*e1997b9aSAndroid Build Coastguard Worker             blob: None,
2370*e1997b9aSAndroid Build Coastguard Worker         },
2371*e1997b9aSAndroid Build Coastguard Worker         OWNER as u32,
2372*e1997b9aSAndroid Build Coastguard Worker         123,
2373*e1997b9aSAndroid Build Coastguard Worker         key_perm_set![KeyPerm::Use],
2374*e1997b9aSAndroid Build Coastguard Worker         |_, _| Ok(()),
2375*e1997b9aSAndroid Build Coastguard Worker     )?;
2376*e1997b9aSAndroid Build Coastguard Worker 
2377*e1997b9aSAndroid Build Coastguard Worker     assert_storage_increased(&mut db, vec![MetricsStorage::GRANT], &mut working_stats);
2378*e1997b9aSAndroid Build Coastguard Worker 
2379*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2380*e1997b9aSAndroid Build Coastguard Worker }
2381*e1997b9aSAndroid Build Coastguard Worker 
2382*e1997b9aSAndroid Build Coastguard Worker #[test]
find_auth_token_entry_returns_latest() -> Result<()>2383*e1997b9aSAndroid Build Coastguard Worker fn find_auth_token_entry_returns_latest() -> Result<()> {
2384*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2385*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&HardwareAuthToken {
2386*e1997b9aSAndroid Build Coastguard Worker         challenge: 123,
2387*e1997b9aSAndroid Build Coastguard Worker         userId: 456,
2388*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 789,
2389*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type::ANY,
2390*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 10 },
2391*e1997b9aSAndroid Build Coastguard Worker         mac: b"mac0".to_vec(),
2392*e1997b9aSAndroid Build Coastguard Worker     });
2393*e1997b9aSAndroid Build Coastguard Worker     std::thread::sleep(std::time::Duration::from_millis(1));
2394*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&HardwareAuthToken {
2395*e1997b9aSAndroid Build Coastguard Worker         challenge: 123,
2396*e1997b9aSAndroid Build Coastguard Worker         userId: 457,
2397*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 789,
2398*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type::ANY,
2399*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 12 },
2400*e1997b9aSAndroid Build Coastguard Worker         mac: b"mac1".to_vec(),
2401*e1997b9aSAndroid Build Coastguard Worker     });
2402*e1997b9aSAndroid Build Coastguard Worker     std::thread::sleep(std::time::Duration::from_millis(1));
2403*e1997b9aSAndroid Build Coastguard Worker     db.insert_auth_token(&HardwareAuthToken {
2404*e1997b9aSAndroid Build Coastguard Worker         challenge: 123,
2405*e1997b9aSAndroid Build Coastguard Worker         userId: 458,
2406*e1997b9aSAndroid Build Coastguard Worker         authenticatorId: 789,
2407*e1997b9aSAndroid Build Coastguard Worker         authenticatorType: kmhw_authenticator_type::ANY,
2408*e1997b9aSAndroid Build Coastguard Worker         timestamp: Timestamp { milliSeconds: 3 },
2409*e1997b9aSAndroid Build Coastguard Worker         mac: b"mac2".to_vec(),
2410*e1997b9aSAndroid Build Coastguard Worker     });
2411*e1997b9aSAndroid Build Coastguard Worker     // All three entries are in the database
2412*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(db.perboot.auth_tokens_len(), 3);
2413*e1997b9aSAndroid Build Coastguard Worker     // It selected the most recent timestamp
2414*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(db.find_auth_token_entry(|_| true).unwrap().auth_token.mac, b"mac2".to_vec());
2415*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2416*e1997b9aSAndroid Build Coastguard Worker }
2417*e1997b9aSAndroid Build Coastguard Worker 
blob_count(db: &mut KeystoreDB, sc_type: SubComponentType) -> usize2418*e1997b9aSAndroid Build Coastguard Worker fn blob_count(db: &mut KeystoreDB, sc_type: SubComponentType) -> usize {
2419*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(TransactionBehavior::Deferred, |tx| {
2420*e1997b9aSAndroid Build Coastguard Worker         tx.query_row(
2421*e1997b9aSAndroid Build Coastguard Worker             "SELECT COUNT(*) FROM persistent.blobentry
2422*e1997b9aSAndroid Build Coastguard Worker                      WHERE subcomponent_type = ?;",
2423*e1997b9aSAndroid Build Coastguard Worker             params![sc_type],
2424*e1997b9aSAndroid Build Coastguard Worker             |row| row.get(0),
2425*e1997b9aSAndroid Build Coastguard Worker         )
2426*e1997b9aSAndroid Build Coastguard Worker         .context(ks_err!("Failed to count number of {sc_type:?} blobs"))
2427*e1997b9aSAndroid Build Coastguard Worker         .no_gc()
2428*e1997b9aSAndroid Build Coastguard Worker     })
2429*e1997b9aSAndroid Build Coastguard Worker     .unwrap()
2430*e1997b9aSAndroid Build Coastguard Worker }
2431*e1997b9aSAndroid Build Coastguard Worker 
blob_count_in_state(db: &mut KeystoreDB, sc_type: SubComponentType, state: BlobState) -> usize2432*e1997b9aSAndroid Build Coastguard Worker fn blob_count_in_state(db: &mut KeystoreDB, sc_type: SubComponentType, state: BlobState) -> usize {
2433*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(TransactionBehavior::Deferred, |tx| {
2434*e1997b9aSAndroid Build Coastguard Worker         tx.query_row(
2435*e1997b9aSAndroid Build Coastguard Worker             "SELECT COUNT(*) FROM persistent.blobentry
2436*e1997b9aSAndroid Build Coastguard Worker                      WHERE subcomponent_type = ? AND state = ?;",
2437*e1997b9aSAndroid Build Coastguard Worker             params![sc_type, state],
2438*e1997b9aSAndroid Build Coastguard Worker             |row| row.get(0),
2439*e1997b9aSAndroid Build Coastguard Worker         )
2440*e1997b9aSAndroid Build Coastguard Worker         .context(ks_err!("Failed to count number of {sc_type:?} blobs"))
2441*e1997b9aSAndroid Build Coastguard Worker         .no_gc()
2442*e1997b9aSAndroid Build Coastguard Worker     })
2443*e1997b9aSAndroid Build Coastguard Worker     .unwrap()
2444*e1997b9aSAndroid Build Coastguard Worker }
2445*e1997b9aSAndroid Build Coastguard Worker 
2446*e1997b9aSAndroid Build Coastguard Worker #[test]
test_blobentry_gc() -> Result<()>2447*e1997b9aSAndroid Build Coastguard Worker fn test_blobentry_gc() -> Result<()> {
2448*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2449*e1997b9aSAndroid Build Coastguard Worker     let _key_id1 = make_test_key_entry(&mut db, Domain::APP, 1, "key1", None)?.0;
2450*e1997b9aSAndroid Build Coastguard Worker     let key_guard2 = make_test_key_entry(&mut db, Domain::APP, 2, "key2", None)?;
2451*e1997b9aSAndroid Build Coastguard Worker     let key_guard3 = make_test_key_entry(&mut db, Domain::APP, 3, "key3", None)?;
2452*e1997b9aSAndroid Build Coastguard Worker     let key_id4 = make_test_key_entry(&mut db, Domain::APP, 4, "key4", None)?.0;
2453*e1997b9aSAndroid Build Coastguard Worker     let key_id5 = make_test_key_entry(&mut db, Domain::APP, 5, "key5", None)?.0;
2454*e1997b9aSAndroid Build Coastguard Worker 
2455*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::KEY_BLOB));
2456*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2457*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2458*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2459*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT));
2460*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2461*e1997b9aSAndroid Build Coastguard Worker 
2462*e1997b9aSAndroid Build Coastguard Worker     // Replace the keyblobs for keys 2 and 3.  The previous blobs will still exist.
2463*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_guard2, SubComponentType::KEY_BLOB, Some(&[1, 2, 3]), None)?;
2464*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_guard3, SubComponentType::KEY_BLOB, Some(&[1, 2, 3]), None)?;
2465*e1997b9aSAndroid Build Coastguard Worker 
2466*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(7, blob_count(&mut db, SubComponentType::KEY_BLOB));
2467*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2468*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2469*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2470*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT));
2471*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2472*e1997b9aSAndroid Build Coastguard Worker 
2473*e1997b9aSAndroid Build Coastguard Worker     // Delete keys 4 and 5.  The keyblobs aren't removed yet.
2474*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_delete_test_keys"), |tx| {
2475*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::mark_unreferenced(tx, key_id4)?;
2476*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::mark_unreferenced(tx, key_id5)?;
2477*e1997b9aSAndroid Build Coastguard Worker         Ok(()).no_gc()
2478*e1997b9aSAndroid Build Coastguard Worker     })
2479*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
2480*e1997b9aSAndroid Build Coastguard Worker 
2481*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(7, blob_count(&mut db, SubComponentType::KEY_BLOB));
2482*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2483*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2484*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2485*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT));
2486*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2487*e1997b9aSAndroid Build Coastguard Worker 
2488*e1997b9aSAndroid Build Coastguard Worker     // First garbage collection should return all 4 blobentry rows that are no longer current for
2489*e1997b9aSAndroid Build Coastguard Worker     // their key.
2490*e1997b9aSAndroid Build Coastguard Worker     let superseded = db.handle_next_superseded_blobs(&[], 20).unwrap();
2491*e1997b9aSAndroid Build Coastguard Worker     let superseded_ids: Vec<i64> = superseded.iter().map(|v| v.blob_id).collect();
2492*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(4, superseded.len());
2493*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(7, blob_count(&mut db, SubComponentType::KEY_BLOB));
2494*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2495*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2496*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2497*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT));
2498*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2499*e1997b9aSAndroid Build Coastguard Worker 
2500*e1997b9aSAndroid Build Coastguard Worker     // Feed the superseded blob IDs back in, to trigger removal of the old KEY_BLOB entries.  As no
2501*e1997b9aSAndroid Build Coastguard Worker     // new superseded KEY_BLOBs are found, the unreferenced CERT/CERT_CHAIN blobs are removed.
2502*e1997b9aSAndroid Build Coastguard Worker     let superseded = db.handle_next_superseded_blobs(&superseded_ids, 20).unwrap();
2503*e1997b9aSAndroid Build Coastguard Worker     let superseded_ids: Vec<i64> = superseded.iter().map(|v| v.blob_id).collect();
2504*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, superseded.len());
2505*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count(&mut db, SubComponentType::KEY_BLOB));
2506*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2507*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2508*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2509*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count(&mut db, SubComponentType::CERT));
2510*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2511*e1997b9aSAndroid Build Coastguard Worker 
2512*e1997b9aSAndroid Build Coastguard Worker     // Nothing left to garbage collect.
2513*e1997b9aSAndroid Build Coastguard Worker     let superseded = db.handle_next_superseded_blobs(&superseded_ids, 20).unwrap();
2514*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, superseded.len());
2515*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count(&mut db, SubComponentType::KEY_BLOB));
2516*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2517*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2518*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(0, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2519*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count(&mut db, SubComponentType::CERT));
2520*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2521*e1997b9aSAndroid Build Coastguard Worker 
2522*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2523*e1997b9aSAndroid Build Coastguard Worker }
2524*e1997b9aSAndroid Build Coastguard Worker 
2525*e1997b9aSAndroid Build Coastguard Worker #[test]
test_upgrade_1_to_2() -> Result<()>2526*e1997b9aSAndroid Build Coastguard Worker fn test_upgrade_1_to_2() -> Result<()> {
2527*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2528*e1997b9aSAndroid Build Coastguard Worker     let _key_id1 = make_test_key_entry(&mut db, Domain::APP, 1, "key1", None)?.0;
2529*e1997b9aSAndroid Build Coastguard Worker     let key_guard2 = make_test_key_entry(&mut db, Domain::APP, 2, "key2", None)?;
2530*e1997b9aSAndroid Build Coastguard Worker     let key_guard3 = make_test_key_entry(&mut db, Domain::APP, 3, "key3", None)?;
2531*e1997b9aSAndroid Build Coastguard Worker     let key_id4 = make_test_key_entry(&mut db, Domain::APP, 4, "key4", None)?.0;
2532*e1997b9aSAndroid Build Coastguard Worker     let key_id5 = make_test_key_entry(&mut db, Domain::APP, 5, "key5", None)?.0;
2533*e1997b9aSAndroid Build Coastguard Worker 
2534*e1997b9aSAndroid Build Coastguard Worker     // Replace the keyblobs for keys 2 and 3.  The previous blobs will still exist.
2535*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_guard2, SubComponentType::KEY_BLOB, Some(&[1, 2, 3]), None)?;
2536*e1997b9aSAndroid Build Coastguard Worker     db.set_blob(&key_guard3, SubComponentType::KEY_BLOB, Some(&[1, 2, 3]), None)?;
2537*e1997b9aSAndroid Build Coastguard Worker 
2538*e1997b9aSAndroid Build Coastguard Worker     // Delete keys 4 and 5.  The keyblobs aren't removed yet.
2539*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_delete_test_keys"), |tx| {
2540*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::mark_unreferenced(tx, key_id4)?;
2541*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::mark_unreferenced(tx, key_id5)?;
2542*e1997b9aSAndroid Build Coastguard Worker         Ok(()).no_gc()
2543*e1997b9aSAndroid Build Coastguard Worker     })
2544*e1997b9aSAndroid Build Coastguard Worker     .unwrap();
2545*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(7, blob_count(&mut db, SubComponentType::KEY_BLOB));
2546*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT));
2547*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2548*e1997b9aSAndroid Build Coastguard Worker 
2549*e1997b9aSAndroid Build Coastguard Worker     // Manually downgrade the database to the v1 schema.
2550*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("TX_downgrade_2_to_1"), |tx| {
2551*e1997b9aSAndroid Build Coastguard Worker         tx.execute("DROP INDEX persistent.keyentry_state_index;", params!())?;
2552*e1997b9aSAndroid Build Coastguard Worker         tx.execute("DROP INDEX persistent.blobentry_state_index;", params!())?;
2553*e1997b9aSAndroid Build Coastguard Worker         tx.execute("ALTER TABLE persistent.blobentry DROP COLUMN state;", params!())?;
2554*e1997b9aSAndroid Build Coastguard Worker         Ok(()).no_gc()
2555*e1997b9aSAndroid Build Coastguard Worker     })?;
2556*e1997b9aSAndroid Build Coastguard Worker 
2557*e1997b9aSAndroid Build Coastguard Worker     // Run the upgrade process.
2558*e1997b9aSAndroid Build Coastguard Worker     let version = db.with_transaction(Immediate("TX_upgrade_1_to_2"), |tx| {
2559*e1997b9aSAndroid Build Coastguard Worker         KeystoreDB::from_1_to_2(tx).no_gc()
2560*e1997b9aSAndroid Build Coastguard Worker     })?;
2561*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(version, 2);
2562*e1997b9aSAndroid Build Coastguard Worker 
2563*e1997b9aSAndroid Build Coastguard Worker     // Check blobs have acquired the right `state` values.
2564*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(7, blob_count(&mut db, SubComponentType::KEY_BLOB));
2565*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(3, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Current));
2566*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Superseded));
2567*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(2, blob_count_in_state(&mut db, SubComponentType::KEY_BLOB, BlobState::Orphaned));
2568*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT));
2569*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(5, blob_count(&mut db, SubComponentType::CERT_CHAIN));
2570*e1997b9aSAndroid Build Coastguard Worker 
2571*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2572*e1997b9aSAndroid Build Coastguard Worker }
2573*e1997b9aSAndroid Build Coastguard Worker 
2574*e1997b9aSAndroid Build Coastguard Worker #[test]
test_load_key_descriptor() -> Result<()>2575*e1997b9aSAndroid Build Coastguard Worker fn test_load_key_descriptor() -> Result<()> {
2576*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2577*e1997b9aSAndroid Build Coastguard Worker     let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None)?.0;
2578*e1997b9aSAndroid Build Coastguard Worker 
2579*e1997b9aSAndroid Build Coastguard Worker     let key = db.load_key_descriptor(key_id)?.unwrap();
2580*e1997b9aSAndroid Build Coastguard Worker 
2581*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key.domain, Domain::APP);
2582*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key.nspace, 1);
2583*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(key.alias, Some(TEST_ALIAS.to_string()));
2584*e1997b9aSAndroid Build Coastguard Worker 
2585*e1997b9aSAndroid Build Coastguard Worker     // No such id
2586*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(db.load_key_descriptor(key_id + 1)?, None);
2587*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2588*e1997b9aSAndroid Build Coastguard Worker }
2589*e1997b9aSAndroid Build Coastguard Worker 
2590*e1997b9aSAndroid Build Coastguard Worker #[test]
test_get_list_app_uids_for_sid() -> Result<()>2591*e1997b9aSAndroid Build Coastguard Worker fn test_get_list_app_uids_for_sid() -> Result<()> {
2592*e1997b9aSAndroid Build Coastguard Worker     let uid: i32 = 1;
2593*e1997b9aSAndroid Build Coastguard Worker     let uid_offset: i64 = (uid as i64) * (AID_USER_OFFSET as i64);
2594*e1997b9aSAndroid Build Coastguard Worker     let first_sid = 667;
2595*e1997b9aSAndroid Build Coastguard Worker     let second_sid = 669;
2596*e1997b9aSAndroid Build Coastguard Worker     let first_app_id: i64 = 123 + uid_offset;
2597*e1997b9aSAndroid Build Coastguard Worker     let second_app_id: i64 = 456 + uid_offset;
2598*e1997b9aSAndroid Build Coastguard Worker     let third_app_id: i64 = 789 + uid_offset;
2599*e1997b9aSAndroid Build Coastguard Worker     let unrelated_app_id: i64 = 1011 + uid_offset;
2600*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2601*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(
2602*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2603*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2604*e1997b9aSAndroid Build Coastguard Worker         first_app_id,
2605*e1997b9aSAndroid Build Coastguard Worker         TEST_ALIAS,
2606*e1997b9aSAndroid Build Coastguard Worker         None,
2607*e1997b9aSAndroid Build Coastguard Worker         &[first_sid],
2608*e1997b9aSAndroid Build Coastguard Worker     )
2609*e1997b9aSAndroid Build Coastguard Worker     .context("test_get_list_app_uids_for_sid")?;
2610*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(
2611*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2612*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2613*e1997b9aSAndroid Build Coastguard Worker         second_app_id,
2614*e1997b9aSAndroid Build Coastguard Worker         "alias2",
2615*e1997b9aSAndroid Build Coastguard Worker         None,
2616*e1997b9aSAndroid Build Coastguard Worker         &[first_sid],
2617*e1997b9aSAndroid Build Coastguard Worker     )
2618*e1997b9aSAndroid Build Coastguard Worker     .context("test_get_list_app_uids_for_sid")?;
2619*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(
2620*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2621*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2622*e1997b9aSAndroid Build Coastguard Worker         second_app_id,
2623*e1997b9aSAndroid Build Coastguard Worker         TEST_ALIAS,
2624*e1997b9aSAndroid Build Coastguard Worker         None,
2625*e1997b9aSAndroid Build Coastguard Worker         &[second_sid],
2626*e1997b9aSAndroid Build Coastguard Worker     )
2627*e1997b9aSAndroid Build Coastguard Worker     .context("test_get_list_app_uids_for_sid")?;
2628*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(
2629*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2630*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2631*e1997b9aSAndroid Build Coastguard Worker         third_app_id,
2632*e1997b9aSAndroid Build Coastguard Worker         "alias3",
2633*e1997b9aSAndroid Build Coastguard Worker         None,
2634*e1997b9aSAndroid Build Coastguard Worker         &[second_sid],
2635*e1997b9aSAndroid Build Coastguard Worker     )
2636*e1997b9aSAndroid Build Coastguard Worker     .context("test_get_list_app_uids_for_sid")?;
2637*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(&mut db, Domain::APP, unrelated_app_id, TEST_ALIAS, None, &[])
2638*e1997b9aSAndroid Build Coastguard Worker         .context("test_get_list_app_uids_for_sid")?;
2639*e1997b9aSAndroid Build Coastguard Worker 
2640*e1997b9aSAndroid Build Coastguard Worker     let mut first_sid_apps = db.get_app_uids_affected_by_sid(uid, first_sid)?;
2641*e1997b9aSAndroid Build Coastguard Worker     first_sid_apps.sort();
2642*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(first_sid_apps, vec![first_app_id, second_app_id]);
2643*e1997b9aSAndroid Build Coastguard Worker     let mut second_sid_apps = db.get_app_uids_affected_by_sid(uid, second_sid)?;
2644*e1997b9aSAndroid Build Coastguard Worker     second_sid_apps.sort();
2645*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(second_sid_apps, vec![second_app_id, third_app_id]);
2646*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2647*e1997b9aSAndroid Build Coastguard Worker }
2648*e1997b9aSAndroid Build Coastguard Worker 
2649*e1997b9aSAndroid Build Coastguard Worker #[test]
test_get_list_app_uids_with_multiple_sids() -> Result<()>2650*e1997b9aSAndroid Build Coastguard Worker fn test_get_list_app_uids_with_multiple_sids() -> Result<()> {
2651*e1997b9aSAndroid Build Coastguard Worker     let uid: i32 = 1;
2652*e1997b9aSAndroid Build Coastguard Worker     let uid_offset: i64 = (uid as i64) * (AID_USER_OFFSET as i64);
2653*e1997b9aSAndroid Build Coastguard Worker     let first_sid = 667;
2654*e1997b9aSAndroid Build Coastguard Worker     let second_sid = 669;
2655*e1997b9aSAndroid Build Coastguard Worker     let third_sid = 772;
2656*e1997b9aSAndroid Build Coastguard Worker     let first_app_id: i64 = 123 + uid_offset;
2657*e1997b9aSAndroid Build Coastguard Worker     let second_app_id: i64 = 456 + uid_offset;
2658*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db()?;
2659*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(
2660*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2661*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2662*e1997b9aSAndroid Build Coastguard Worker         first_app_id,
2663*e1997b9aSAndroid Build Coastguard Worker         TEST_ALIAS,
2664*e1997b9aSAndroid Build Coastguard Worker         None,
2665*e1997b9aSAndroid Build Coastguard Worker         &[first_sid, second_sid],
2666*e1997b9aSAndroid Build Coastguard Worker     )
2667*e1997b9aSAndroid Build Coastguard Worker     .context("test_get_list_app_uids_for_sid")?;
2668*e1997b9aSAndroid Build Coastguard Worker     make_test_key_entry_with_sids(
2669*e1997b9aSAndroid Build Coastguard Worker         &mut db,
2670*e1997b9aSAndroid Build Coastguard Worker         Domain::APP,
2671*e1997b9aSAndroid Build Coastguard Worker         second_app_id,
2672*e1997b9aSAndroid Build Coastguard Worker         "alias2",
2673*e1997b9aSAndroid Build Coastguard Worker         None,
2674*e1997b9aSAndroid Build Coastguard Worker         &[second_sid, third_sid],
2675*e1997b9aSAndroid Build Coastguard Worker     )
2676*e1997b9aSAndroid Build Coastguard Worker     .context("test_get_list_app_uids_for_sid")?;
2677*e1997b9aSAndroid Build Coastguard Worker 
2678*e1997b9aSAndroid Build Coastguard Worker     let first_sid_apps = db.get_app_uids_affected_by_sid(uid, first_sid)?;
2679*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(first_sid_apps, vec![first_app_id]);
2680*e1997b9aSAndroid Build Coastguard Worker 
2681*e1997b9aSAndroid Build Coastguard Worker     let mut second_sid_apps = db.get_app_uids_affected_by_sid(uid, second_sid)?;
2682*e1997b9aSAndroid Build Coastguard Worker     second_sid_apps.sort();
2683*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(second_sid_apps, vec![first_app_id, second_app_id]);
2684*e1997b9aSAndroid Build Coastguard Worker 
2685*e1997b9aSAndroid Build Coastguard Worker     let third_sid_apps = db.get_app_uids_affected_by_sid(uid, third_sid)?;
2686*e1997b9aSAndroid Build Coastguard Worker     assert_eq!(third_sid_apps, vec![second_app_id]);
2687*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2688*e1997b9aSAndroid Build Coastguard Worker }
2689*e1997b9aSAndroid Build Coastguard Worker 
2690*e1997b9aSAndroid Build Coastguard Worker // Starting from `next_keyid`, add keys to the database until the count reaches
2691*e1997b9aSAndroid Build Coastguard Worker // `key_count`.  (`next_keyid` is assumed to indicate how many rows already exist.)
db_populate_keys(db: &mut KeystoreDB, next_keyid: usize, key_count: usize)2692*e1997b9aSAndroid Build Coastguard Worker fn db_populate_keys(db: &mut KeystoreDB, next_keyid: usize, key_count: usize) {
2693*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(Immediate("test_keyentry"), |tx| {
2694*e1997b9aSAndroid Build Coastguard Worker         for next_keyid in next_keyid..key_count {
2695*e1997b9aSAndroid Build Coastguard Worker             tx.execute(
2696*e1997b9aSAndroid Build Coastguard Worker                 "INSERT into persistent.keyentry
2697*e1997b9aSAndroid Build Coastguard Worker                         (id, key_type, domain, namespace, alias, state, km_uuid)
2698*e1997b9aSAndroid Build Coastguard Worker                         VALUES(?, ?, ?, ?, ?, ?, ?);",
2699*e1997b9aSAndroid Build Coastguard Worker                 params![
2700*e1997b9aSAndroid Build Coastguard Worker                     next_keyid,
2701*e1997b9aSAndroid Build Coastguard Worker                     KeyType::Client,
2702*e1997b9aSAndroid Build Coastguard Worker                     Domain::APP.0 as u32,
2703*e1997b9aSAndroid Build Coastguard Worker                     10001,
2704*e1997b9aSAndroid Build Coastguard Worker                     &format!("alias-{next_keyid}"),
2705*e1997b9aSAndroid Build Coastguard Worker                     KeyLifeCycle::Live,
2706*e1997b9aSAndroid Build Coastguard Worker                     KEYSTORE_UUID,
2707*e1997b9aSAndroid Build Coastguard Worker                 ],
2708*e1997b9aSAndroid Build Coastguard Worker             )?;
2709*e1997b9aSAndroid Build Coastguard Worker             tx.execute(
2710*e1997b9aSAndroid Build Coastguard Worker                 "INSERT INTO persistent.blobentry
2711*e1997b9aSAndroid Build Coastguard Worker                          (subcomponent_type, keyentryid, blob) VALUES (?, ?, ?);",
2712*e1997b9aSAndroid Build Coastguard Worker                 params![SubComponentType::KEY_BLOB, next_keyid, TEST_KEY_BLOB],
2713*e1997b9aSAndroid Build Coastguard Worker             )?;
2714*e1997b9aSAndroid Build Coastguard Worker             tx.execute(
2715*e1997b9aSAndroid Build Coastguard Worker                 "INSERT INTO persistent.blobentry
2716*e1997b9aSAndroid Build Coastguard Worker                          (subcomponent_type, keyentryid, blob) VALUES (?, ?, ?);",
2717*e1997b9aSAndroid Build Coastguard Worker                 params![SubComponentType::CERT, next_keyid, TEST_CERT_BLOB],
2718*e1997b9aSAndroid Build Coastguard Worker             )?;
2719*e1997b9aSAndroid Build Coastguard Worker             tx.execute(
2720*e1997b9aSAndroid Build Coastguard Worker                 "INSERT INTO persistent.blobentry
2721*e1997b9aSAndroid Build Coastguard Worker                          (subcomponent_type, keyentryid, blob) VALUES (?, ?, ?);",
2722*e1997b9aSAndroid Build Coastguard Worker                 params![SubComponentType::CERT_CHAIN, next_keyid, TEST_CERT_CHAIN_BLOB],
2723*e1997b9aSAndroid Build Coastguard Worker             )?;
2724*e1997b9aSAndroid Build Coastguard Worker         }
2725*e1997b9aSAndroid Build Coastguard Worker         Ok(()).no_gc()
2726*e1997b9aSAndroid Build Coastguard Worker     })
2727*e1997b9aSAndroid Build Coastguard Worker     .unwrap()
2728*e1997b9aSAndroid Build Coastguard Worker }
2729*e1997b9aSAndroid Build Coastguard Worker 
2730*e1997b9aSAndroid Build Coastguard Worker /// Run the provided `test_fn` against the database at various increasing stages of
2731*e1997b9aSAndroid Build Coastguard Worker /// database population.
run_with_many_keys<F, T>(max_count: usize, test_fn: F) -> Result<()> where F: Fn(&mut KeystoreDB) -> T,2732*e1997b9aSAndroid Build Coastguard Worker fn run_with_many_keys<F, T>(max_count: usize, test_fn: F) -> Result<()>
2733*e1997b9aSAndroid Build Coastguard Worker where
2734*e1997b9aSAndroid Build Coastguard Worker     F: Fn(&mut KeystoreDB) -> T,
2735*e1997b9aSAndroid Build Coastguard Worker {
2736*e1997b9aSAndroid Build Coastguard Worker     prep_and_run_with_many_keys(max_count, |_db| (), test_fn)
2737*e1997b9aSAndroid Build Coastguard Worker }
2738*e1997b9aSAndroid Build Coastguard Worker 
2739*e1997b9aSAndroid Build Coastguard Worker /// Run the provided `test_fn` against the database at various increasing stages of
2740*e1997b9aSAndroid Build Coastguard Worker /// database population.
prep_and_run_with_many_keys<F, T, P>(max_count: usize, prep_fn: P, test_fn: F) -> Result<()> where F: Fn(&mut KeystoreDB) -> T, P: Fn(&mut KeystoreDB),2741*e1997b9aSAndroid Build Coastguard Worker fn prep_and_run_with_many_keys<F, T, P>(max_count: usize, prep_fn: P, test_fn: F) -> Result<()>
2742*e1997b9aSAndroid Build Coastguard Worker where
2743*e1997b9aSAndroid Build Coastguard Worker     F: Fn(&mut KeystoreDB) -> T,
2744*e1997b9aSAndroid Build Coastguard Worker     P: Fn(&mut KeystoreDB),
2745*e1997b9aSAndroid Build Coastguard Worker {
2746*e1997b9aSAndroid Build Coastguard Worker     android_logger::init_once(
2747*e1997b9aSAndroid Build Coastguard Worker         android_logger::Config::default()
2748*e1997b9aSAndroid Build Coastguard Worker             .with_tag("keystore2_test")
2749*e1997b9aSAndroid Build Coastguard Worker             .with_max_level(log::LevelFilter::Debug),
2750*e1997b9aSAndroid Build Coastguard Worker     );
2751*e1997b9aSAndroid Build Coastguard Worker     // Put the test database on disk for a more realistic result.
2752*e1997b9aSAndroid Build Coastguard Worker     let db_root = tempfile::Builder::new().prefix("ks2db-test-").tempdir().unwrap();
2753*e1997b9aSAndroid Build Coastguard Worker     let mut db_path = db_root.path().to_owned();
2754*e1997b9aSAndroid Build Coastguard Worker     db_path.push("ks2-test.sqlite");
2755*e1997b9aSAndroid Build Coastguard Worker     let mut db = new_test_db_at(&db_path.to_string_lossy())?;
2756*e1997b9aSAndroid Build Coastguard Worker 
2757*e1997b9aSAndroid Build Coastguard Worker     println!("\nNumber_of_keys,time_in_s");
2758*e1997b9aSAndroid Build Coastguard Worker     let mut key_count = 10;
2759*e1997b9aSAndroid Build Coastguard Worker     let mut next_keyid = 0;
2760*e1997b9aSAndroid Build Coastguard Worker     while key_count < max_count {
2761*e1997b9aSAndroid Build Coastguard Worker         db_populate_keys(&mut db, next_keyid, key_count);
2762*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(db_key_count(&mut db), key_count);
2763*e1997b9aSAndroid Build Coastguard Worker 
2764*e1997b9aSAndroid Build Coastguard Worker         // Perform any test-specific preparation
2765*e1997b9aSAndroid Build Coastguard Worker         prep_fn(&mut db);
2766*e1997b9aSAndroid Build Coastguard Worker 
2767*e1997b9aSAndroid Build Coastguard Worker         // Time execution of the test function.
2768*e1997b9aSAndroid Build Coastguard Worker         let start = std::time::Instant::now();
2769*e1997b9aSAndroid Build Coastguard Worker         let _result = test_fn(&mut db);
2770*e1997b9aSAndroid Build Coastguard Worker         println!("{key_count}, {}", start.elapsed().as_secs_f64());
2771*e1997b9aSAndroid Build Coastguard Worker 
2772*e1997b9aSAndroid Build Coastguard Worker         next_keyid = key_count;
2773*e1997b9aSAndroid Build Coastguard Worker         key_count *= 2;
2774*e1997b9aSAndroid Build Coastguard Worker     }
2775*e1997b9aSAndroid Build Coastguard Worker 
2776*e1997b9aSAndroid Build Coastguard Worker     Ok(())
2777*e1997b9aSAndroid Build Coastguard Worker }
2778*e1997b9aSAndroid Build Coastguard Worker 
db_key_count(db: &mut KeystoreDB) -> usize2779*e1997b9aSAndroid Build Coastguard Worker fn db_key_count(db: &mut KeystoreDB) -> usize {
2780*e1997b9aSAndroid Build Coastguard Worker     db.with_transaction(TransactionBehavior::Deferred, |tx| {
2781*e1997b9aSAndroid Build Coastguard Worker         tx.query_row(
2782*e1997b9aSAndroid Build Coastguard Worker             "SELECT COUNT(*) FROM persistent.keyentry
2783*e1997b9aSAndroid Build Coastguard Worker                          WHERE domain = ? AND state = ? AND key_type = ?;",
2784*e1997b9aSAndroid Build Coastguard Worker             params![Domain::APP.0 as u32, KeyLifeCycle::Live, KeyType::Client],
2785*e1997b9aSAndroid Build Coastguard Worker             |row| row.get::<usize, usize>(0),
2786*e1997b9aSAndroid Build Coastguard Worker         )
2787*e1997b9aSAndroid Build Coastguard Worker         .context(ks_err!("Failed to count number of keys."))
2788*e1997b9aSAndroid Build Coastguard Worker         .no_gc()
2789*e1997b9aSAndroid Build Coastguard Worker     })
2790*e1997b9aSAndroid Build Coastguard Worker     .unwrap()
2791*e1997b9aSAndroid Build Coastguard Worker }
2792*e1997b9aSAndroid Build Coastguard Worker 
2793*e1997b9aSAndroid Build Coastguard Worker #[test]
test_handle_superseded_with_many_keys() -> Result<()>2794*e1997b9aSAndroid Build Coastguard Worker fn test_handle_superseded_with_many_keys() -> Result<()> {
2795*e1997b9aSAndroid Build Coastguard Worker     run_with_many_keys(1_000_000, |db| db.handle_next_superseded_blobs(&[], 20))
2796*e1997b9aSAndroid Build Coastguard Worker }
2797*e1997b9aSAndroid Build Coastguard Worker 
2798*e1997b9aSAndroid Build Coastguard Worker #[test]
test_get_storage_stats_with_many_keys() -> Result<()>2799*e1997b9aSAndroid Build Coastguard Worker fn test_get_storage_stats_with_many_keys() -> Result<()> {
2800*e1997b9aSAndroid Build Coastguard Worker     use android_security_metrics::aidl::android::security::metrics::Storage::Storage as MetricsStorage;
2801*e1997b9aSAndroid Build Coastguard Worker     run_with_many_keys(1_000_000, |db| {
2802*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::DATABASE).unwrap();
2803*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_ENTRY).unwrap();
2804*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_ENTRY_ID_INDEX).unwrap();
2805*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_ENTRY_DOMAIN_NAMESPACE_INDEX).unwrap();
2806*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::BLOB_ENTRY).unwrap();
2807*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::BLOB_ENTRY_KEY_ENTRY_ID_INDEX).unwrap();
2808*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_PARAMETER).unwrap();
2809*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_PARAMETER_KEY_ENTRY_ID_INDEX).unwrap();
2810*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_METADATA).unwrap();
2811*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::KEY_METADATA_KEY_ENTRY_ID_INDEX).unwrap();
2812*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::GRANT).unwrap();
2813*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::AUTH_TOKEN).unwrap();
2814*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::BLOB_METADATA).unwrap();
2815*e1997b9aSAndroid Build Coastguard Worker         db.get_storage_stat(MetricsStorage::BLOB_METADATA_BLOB_ENTRY_ID_INDEX).unwrap();
2816*e1997b9aSAndroid Build Coastguard Worker     })
2817*e1997b9aSAndroid Build Coastguard Worker }
2818*e1997b9aSAndroid Build Coastguard Worker 
2819*e1997b9aSAndroid Build Coastguard Worker #[test]
test_list_keys_with_many_keys() -> Result<()>2820*e1997b9aSAndroid Build Coastguard Worker fn test_list_keys_with_many_keys() -> Result<()> {
2821*e1997b9aSAndroid Build Coastguard Worker     run_with_many_keys(1_000_000, |db: &mut KeystoreDB| -> Result<()> {
2822*e1997b9aSAndroid Build Coastguard Worker         // Behave equivalently to how clients list aliases.
2823*e1997b9aSAndroid Build Coastguard Worker         let domain = Domain::APP;
2824*e1997b9aSAndroid Build Coastguard Worker         let namespace = 10001;
2825*e1997b9aSAndroid Build Coastguard Worker         let mut start_past: Option<String> = None;
2826*e1997b9aSAndroid Build Coastguard Worker         let mut count = 0;
2827*e1997b9aSAndroid Build Coastguard Worker         let mut batches = 0;
2828*e1997b9aSAndroid Build Coastguard Worker         loop {
2829*e1997b9aSAndroid Build Coastguard Worker             let keys = db
2830*e1997b9aSAndroid Build Coastguard Worker                 .list_past_alias(domain, namespace, KeyType::Client, start_past.as_deref())
2831*e1997b9aSAndroid Build Coastguard Worker                 .unwrap();
2832*e1997b9aSAndroid Build Coastguard Worker             let batch_size = crate::utils::estimate_safe_amount_to_return(
2833*e1997b9aSAndroid Build Coastguard Worker                 domain,
2834*e1997b9aSAndroid Build Coastguard Worker                 namespace,
2835*e1997b9aSAndroid Build Coastguard Worker                 None,
2836*e1997b9aSAndroid Build Coastguard Worker                 &keys,
2837*e1997b9aSAndroid Build Coastguard Worker                 crate::utils::RESPONSE_SIZE_LIMIT,
2838*e1997b9aSAndroid Build Coastguard Worker             );
2839*e1997b9aSAndroid Build Coastguard Worker             let batch = &keys[..batch_size];
2840*e1997b9aSAndroid Build Coastguard Worker             count += batch.len();
2841*e1997b9aSAndroid Build Coastguard Worker             match batch.last() {
2842*e1997b9aSAndroid Build Coastguard Worker                 Some(key) => start_past.clone_from(&key.alias),
2843*e1997b9aSAndroid Build Coastguard Worker                 None => {
2844*e1997b9aSAndroid Build Coastguard Worker                     log::info!("got {count} keys in {batches} non-empty batches");
2845*e1997b9aSAndroid Build Coastguard Worker                     return Ok(());
2846*e1997b9aSAndroid Build Coastguard Worker                 }
2847*e1997b9aSAndroid Build Coastguard Worker             }
2848*e1997b9aSAndroid Build Coastguard Worker             batches += 1;
2849*e1997b9aSAndroid Build Coastguard Worker         }
2850*e1997b9aSAndroid Build Coastguard Worker     })
2851*e1997b9aSAndroid Build Coastguard Worker }
2852*e1997b9aSAndroid Build Coastguard Worker 
2853*e1997b9aSAndroid Build Coastguard Worker #[test]
test_upgrade_1_to_2_with_many_keys() -> Result<()>2854*e1997b9aSAndroid Build Coastguard Worker fn test_upgrade_1_to_2_with_many_keys() -> Result<()> {
2855*e1997b9aSAndroid Build Coastguard Worker     prep_and_run_with_many_keys(
2856*e1997b9aSAndroid Build Coastguard Worker         1_000_000,
2857*e1997b9aSAndroid Build Coastguard Worker         |db: &mut KeystoreDB| {
2858*e1997b9aSAndroid Build Coastguard Worker             // Manually downgrade the database to the v1 schema.
2859*e1997b9aSAndroid Build Coastguard Worker             db.with_transaction(Immediate("TX_downgrade_2_to_1"), |tx| {
2860*e1997b9aSAndroid Build Coastguard Worker                 tx.execute("DROP INDEX persistent.keyentry_state_index;", params!())?;
2861*e1997b9aSAndroid Build Coastguard Worker                 tx.execute("DROP INDEX persistent.blobentry_state_index;", params!())?;
2862*e1997b9aSAndroid Build Coastguard Worker                 tx.execute("ALTER TABLE persistent.blobentry DROP COLUMN state;", params!())?;
2863*e1997b9aSAndroid Build Coastguard Worker                 Ok(()).no_gc()
2864*e1997b9aSAndroid Build Coastguard Worker             })
2865*e1997b9aSAndroid Build Coastguard Worker             .unwrap();
2866*e1997b9aSAndroid Build Coastguard Worker         },
2867*e1997b9aSAndroid Build Coastguard Worker         |db: &mut KeystoreDB| -> Result<()> {
2868*e1997b9aSAndroid Build Coastguard Worker             // Run the upgrade process.
2869*e1997b9aSAndroid Build Coastguard Worker             db.with_transaction(Immediate("TX_upgrade_1_to_2"), |tx| {
2870*e1997b9aSAndroid Build Coastguard Worker                 KeystoreDB::from_1_to_2(tx).no_gc()
2871*e1997b9aSAndroid Build Coastguard Worker             })?;
2872*e1997b9aSAndroid Build Coastguard Worker             Ok(())
2873*e1997b9aSAndroid Build Coastguard Worker         },
2874*e1997b9aSAndroid Build Coastguard Worker     )
2875*e1997b9aSAndroid Build Coastguard Worker }
2876