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, ¶ms)?;
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, ¶ms)?;
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, ¶ms)?;
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, ¶ms)?;
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