Move large test modules into separate files
This complies better with the Android Rust style guide, and makes it
easier to navigate the code.
Test: keystore2_test libwatchdog_rs.test librkpd_client.test
Change-Id: Iceb49e309af66ec16d31da66b328936b0312061a
diff --git a/keystore2/src/super_key/tests.rs b/keystore2/src/super_key/tests.rs
new file mode 100644
index 0000000..76a96a7
--- /dev/null
+++ b/keystore2/src/super_key/tests.rs
@@ -0,0 +1,287 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Super-key tests.
+
+use super::*;
+use crate::database::tests::make_bootlevel_key_entry;
+use crate::database::tests::make_test_key_entry;
+use crate::database::tests::new_test_db;
+use rand::prelude::*;
+const USER_ID: u32 = 0;
+const TEST_KEY_ALIAS: &str = "TEST_KEY";
+const TEST_BOOT_KEY_ALIAS: &str = "TEST_BOOT_KEY";
+
+pub fn generate_password_blob() -> Password<'static> {
+ let mut rng = rand::thread_rng();
+ let mut password = vec![0u8; 64];
+ rng.fill_bytes(&mut password);
+
+ let mut zvec = ZVec::new(64).expect("Failed to create ZVec");
+ zvec[..].copy_from_slice(&password[..]);
+
+ Password::Owned(zvec)
+}
+
+fn setup_test(pw: &Password) -> (Arc<RwLock<SuperKeyManager>>, KeystoreDB, LegacyImporter) {
+ let mut keystore_db = new_test_db().unwrap();
+ let mut legacy_importer = LegacyImporter::new(Arc::new(Default::default()));
+ legacy_importer.set_empty();
+ let skm: Arc<RwLock<SuperKeyManager>> = Default::default();
+ assert!(skm
+ .write()
+ .unwrap()
+ .initialize_user(&mut keystore_db, &legacy_importer, USER_ID, pw, false)
+ .is_ok());
+ (skm, keystore_db, legacy_importer)
+}
+
+fn assert_unlocked(
+ skm: &Arc<RwLock<SuperKeyManager>>,
+ keystore_db: &mut KeystoreDB,
+ legacy_importer: &LegacyImporter,
+ user_id: u32,
+ err_msg: &str,
+) {
+ let user_state =
+ skm.write().unwrap().get_user_state(keystore_db, legacy_importer, user_id).unwrap();
+ match user_state {
+ UserState::AfterFirstUnlock(_) => {}
+ _ => panic!("{}", err_msg),
+ }
+}
+
+fn assert_locked(
+ skm: &Arc<RwLock<SuperKeyManager>>,
+ keystore_db: &mut KeystoreDB,
+ legacy_importer: &LegacyImporter,
+ user_id: u32,
+ err_msg: &str,
+) {
+ let user_state =
+ skm.write().unwrap().get_user_state(keystore_db, legacy_importer, user_id).unwrap();
+ match user_state {
+ UserState::BeforeFirstUnlock => {}
+ _ => panic!("{}", err_msg),
+ }
+}
+
+fn assert_uninitialized(
+ skm: &Arc<RwLock<SuperKeyManager>>,
+ keystore_db: &mut KeystoreDB,
+ legacy_importer: &LegacyImporter,
+ user_id: u32,
+ err_msg: &str,
+) {
+ let user_state =
+ skm.write().unwrap().get_user_state(keystore_db, legacy_importer, user_id).unwrap();
+ match user_state {
+ UserState::Uninitialized => {}
+ _ => panic!("{}", err_msg),
+ }
+}
+
+#[test]
+fn test_initialize_user() {
+ let pw: Password = generate_password_blob();
+ let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
+ assert_unlocked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was not unlocked after initialization!",
+ );
+}
+
+#[test]
+fn test_unlock_user() {
+ let pw: Password = generate_password_blob();
+ let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
+ assert_unlocked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was not unlocked after initialization!",
+ );
+
+ skm.write().unwrap().data.user_keys.clear();
+ assert_locked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "Clearing the cache did not lock the user!",
+ );
+
+ assert!(skm
+ .write()
+ .unwrap()
+ .unlock_user(&mut keystore_db, &legacy_importer, USER_ID, &pw)
+ .is_ok());
+ assert_unlocked(&skm, &mut keystore_db, &legacy_importer, USER_ID, "The user did not unlock!");
+}
+
+#[test]
+fn test_unlock_wrong_password() {
+ let pw: Password = generate_password_blob();
+ let wrong_pw: Password = generate_password_blob();
+ let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
+ assert_unlocked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was not unlocked after initialization!",
+ );
+
+ skm.write().unwrap().data.user_keys.clear();
+ assert_locked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "Clearing the cache did not lock the user!",
+ );
+
+ assert!(skm
+ .write()
+ .unwrap()
+ .unlock_user(&mut keystore_db, &legacy_importer, USER_ID, &wrong_pw)
+ .is_err());
+ assert_locked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was unlocked with an incorrect password!",
+ );
+}
+
+#[test]
+fn test_unlock_user_idempotent() {
+ let pw: Password = generate_password_blob();
+ let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
+ assert_unlocked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was not unlocked after initialization!",
+ );
+
+ skm.write().unwrap().data.user_keys.clear();
+ assert_locked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "Clearing the cache did not lock the user!",
+ );
+
+ for _ in 0..5 {
+ assert!(skm
+ .write()
+ .unwrap()
+ .unlock_user(&mut keystore_db, &legacy_importer, USER_ID, &pw)
+ .is_ok());
+ assert_unlocked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user did not unlock!",
+ );
+ }
+}
+
+fn test_user_removal(locked: bool) {
+ let pw: Password = generate_password_blob();
+ let (skm, mut keystore_db, legacy_importer) = setup_test(&pw);
+ assert_unlocked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was not unlocked after initialization!",
+ );
+
+ assert!(make_test_key_entry(
+ &mut keystore_db,
+ Domain::APP,
+ USER_ID.into(),
+ TEST_KEY_ALIAS,
+ None
+ )
+ .is_ok());
+ assert!(make_bootlevel_key_entry(
+ &mut keystore_db,
+ Domain::APP,
+ USER_ID.into(),
+ TEST_BOOT_KEY_ALIAS,
+ false
+ )
+ .is_ok());
+
+ assert!(keystore_db
+ .key_exists(Domain::APP, USER_ID.into(), TEST_KEY_ALIAS, KeyType::Client)
+ .unwrap());
+ assert!(keystore_db
+ .key_exists(Domain::APP, USER_ID.into(), TEST_BOOT_KEY_ALIAS, KeyType::Client)
+ .unwrap());
+
+ if locked {
+ skm.write().unwrap().data.user_keys.clear();
+ assert_locked(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "Clearing the cache did not lock the user!",
+ );
+ }
+
+ assert!(skm.write().unwrap().remove_user(&mut keystore_db, &legacy_importer, USER_ID).is_ok());
+ assert_uninitialized(
+ &skm,
+ &mut keystore_db,
+ &legacy_importer,
+ USER_ID,
+ "The user was not removed!",
+ );
+
+ assert!(!skm
+ .write()
+ .unwrap()
+ .super_key_exists_in_db_for_user(&mut keystore_db, &legacy_importer, USER_ID)
+ .unwrap());
+
+ assert!(!keystore_db
+ .key_exists(Domain::APP, USER_ID.into(), TEST_KEY_ALIAS, KeyType::Client)
+ .unwrap());
+ assert!(!keystore_db
+ .key_exists(Domain::APP, USER_ID.into(), TEST_BOOT_KEY_ALIAS, KeyType::Client)
+ .unwrap());
+}
+
+#[test]
+fn test_remove_unlocked_user() {
+ test_user_removal(false);
+}
+
+#[test]
+fn test_remove_locked_user() {
+ test_user_removal(true);
+}