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