Move legacy_blob tests into separate file

This complies better with the Android Rust style guide, and makes it
easier to navigate the code.

Test: keystore2_test
Change-Id: Ia6ea2b0a31f57bfe1b6114b3ce03181c24760310
diff --git a/keystore2/src/legacy_blob.rs b/keystore2/src/legacy_blob.rs
index 2bb7f27..c27a050 100644
--- a/keystore2/src/legacy_blob.rs
+++ b/keystore2/src/legacy_blob.rs
@@ -36,6 +36,9 @@
 
 const SUPPORTED_LEGACY_BLOB_VERSION: u8 = 3;
 
+#[cfg(test)]
+mod tests;
+
 mod flags {
     /// This flag is deprecated. It is here to support keys that have been written with this flag
     /// set, but we don't create any new keys with this flag.
@@ -1645,675 +1648,3 @@
         Ok(())
     }
 }
-
-#[cfg(test)]
-mod test {
-    #![allow(dead_code)]
-    use super::*;
-    use crate::legacy_blob::test_utils::legacy_blob_test_vectors::*;
-    use crate::legacy_blob::test_utils::*;
-    use anyhow::{anyhow, Result};
-    use keystore2_crypto::aes_gcm_decrypt;
-    use keystore2_test_utils::TempDir;
-    use rand::Rng;
-    use std::convert::TryInto;
-    use std::ops::Deref;
-    use std::string::FromUtf8Error;
-
-    #[test]
-    fn decode_encode_alias_test() {
-        static ALIAS: &str = "#({}test[])😗";
-        static ENCODED_ALIAS: &str = "+S+X{}test[]+Y.`-O-H-G";
-        // Second multi byte out of range ------v
-        static ENCODED_ALIAS_ERROR1: &str = "+S+{}test[]+Y";
-        // Incomplete multi byte ------------------------v
-        static ENCODED_ALIAS_ERROR2: &str = "+S+X{}test[]+";
-        // Our encoding: ".`-O-H-G"
-        // is UTF-8: 0xF0 0x9F 0x98 0x97
-        // is UNICODE: U+1F617
-        // is 😗
-        // But +H below is a valid encoding for 0x18 making this sequence invalid UTF-8.
-        static ENCODED_ALIAS_ERROR_UTF8: &str = ".`-O+H-G";
-
-        assert_eq!(ENCODED_ALIAS, &LegacyBlobLoader::encode_alias(ALIAS));
-        assert_eq!(ALIAS, &LegacyBlobLoader::decode_alias(ENCODED_ALIAS).unwrap());
-        assert_eq!(
-            Some(&Error::BadEncoding),
-            LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR1)
-                .unwrap_err()
-                .root_cause()
-                .downcast_ref::<Error>()
-        );
-        assert_eq!(
-            Some(&Error::BadEncoding),
-            LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR2)
-                .unwrap_err()
-                .root_cause()
-                .downcast_ref::<Error>()
-        );
-        assert!(LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR_UTF8)
-            .unwrap_err()
-            .root_cause()
-            .downcast_ref::<FromUtf8Error>()
-            .is_some());
-
-        for _i in 0..100 {
-            // Any valid UTF-8 string should be en- and decoded without loss.
-            let alias_str = rand::thread_rng().gen::<[char; 20]>().iter().collect::<String>();
-            let random_alias = alias_str.as_bytes();
-            let encoded = LegacyBlobLoader::encode_alias(&alias_str);
-            let decoded = match LegacyBlobLoader::decode_alias(&encoded) {
-                Ok(d) => d,
-                Err(_) => panic!("random_alias: {:x?}\nencoded {}", random_alias, encoded),
-            };
-            assert_eq!(random_alias.to_vec(), decoded.bytes().collect::<Vec<u8>>());
-        }
-    }
-
-    #[test]
-    fn read_golden_key_blob_test() -> anyhow::Result<()> {
-        let blob = LegacyBlobLoader::new_from_stream_decrypt_with(&mut &*BLOB, |_, _, _, _, _| {
-            Err(anyhow!("should not be called"))
-        })
-        .unwrap();
-        assert!(!blob.is_encrypted());
-        assert!(!blob.is_fallback());
-        assert!(!blob.is_strongbox());
-        assert!(!blob.is_critical_to_device_encryption());
-        assert_eq!(blob.value(), &BlobValue::Generic([0xde, 0xed, 0xbe, 0xef].to_vec()));
-
-        let blob = LegacyBlobLoader::new_from_stream_decrypt_with(
-            &mut &*REAL_LEGACY_BLOB,
-            |_, _, _, _, _| Err(anyhow!("should not be called")),
-        )
-        .unwrap();
-        assert!(!blob.is_encrypted());
-        assert!(!blob.is_fallback());
-        assert!(!blob.is_strongbox());
-        assert!(!blob.is_critical_to_device_encryption());
-        assert_eq!(
-            blob.value(),
-            &BlobValue::Decrypted(REAL_LEGACY_BLOB_PAYLOAD.try_into().unwrap())
-        );
-        Ok(())
-    }
-
-    #[test]
-    fn read_aes_gcm_encrypted_key_blob_test() {
-        let blob = LegacyBlobLoader::new_from_stream_decrypt_with(
-            &mut &*AES_GCM_ENCRYPTED_BLOB,
-            |d, iv, tag, salt, key_size| {
-                assert_eq!(salt, None);
-                assert_eq!(key_size, None);
-                assert_eq!(
-                    iv,
-                    &[
-                        0xbd, 0xdb, 0x8d, 0x69, 0x72, 0x56, 0xf0, 0xf5, 0xa4, 0x02, 0x88, 0x7f,
-                        0x00, 0x00, 0x00, 0x00,
-                    ]
-                );
-                assert_eq!(
-                    tag,
-                    &[
-                        0x50, 0xd9, 0x97, 0x95, 0x37, 0x6e, 0x28, 0x6a, 0x28, 0x9d, 0x51, 0xb9,
-                        0xb9, 0xe0, 0x0b, 0xc3
-                    ][..]
-                );
-                aes_gcm_decrypt(d, iv, tag, AES_KEY).context("Trying to decrypt blob.")
-            },
-        )
-        .unwrap();
-        assert!(blob.is_encrypted());
-        assert!(!blob.is_fallback());
-        assert!(!blob.is_strongbox());
-        assert!(!blob.is_critical_to_device_encryption());
-
-        assert_eq!(blob.value(), &BlobValue::Decrypted(DECRYPTED_PAYLOAD.try_into().unwrap()));
-    }
-
-    #[test]
-    fn read_golden_key_blob_too_short_test() {
-        let error =
-            LegacyBlobLoader::new_from_stream_decrypt_with(&mut &BLOB[0..15], |_, _, _, _, _| {
-                Err(anyhow!("should not be called"))
-            })
-            .unwrap_err();
-        assert_eq!(Some(&Error::BadLen), error.root_cause().downcast_ref::<Error>());
-    }
-
-    #[test]
-    fn test_is_empty() {
-        let temp_dir = TempDir::new("test_is_empty").expect("Failed to create temp dir.");
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        assert!(legacy_blob_loader.is_empty().expect("Should succeed and be empty."));
-
-        let _db = crate::database::KeystoreDB::new(temp_dir.path(), None)
-            .expect("Failed to open database.");
-
-        assert!(legacy_blob_loader.is_empty().expect("Should succeed and still be empty."));
-
-        std::fs::create_dir(&*temp_dir.build().push("user_0")).expect("Failed to create user_0.");
-
-        assert!(!legacy_blob_loader.is_empty().expect("Should succeed but not be empty."));
-
-        std::fs::create_dir(&*temp_dir.build().push("user_10")).expect("Failed to create user_10.");
-
-        assert!(!legacy_blob_loader.is_empty().expect("Should succeed but still not be empty."));
-
-        std::fs::remove_dir_all(&*temp_dir.build().push("user_0"))
-            .expect("Failed to remove user_0.");
-
-        assert!(!legacy_blob_loader.is_empty().expect("Should succeed but still not be empty."));
-
-        std::fs::remove_dir_all(&*temp_dir.build().push("user_10"))
-            .expect("Failed to remove user_10.");
-
-        assert!(legacy_blob_loader.is_empty().expect("Should succeed and be empty again."));
-    }
-
-    #[test]
-    fn test_legacy_blobs() -> anyhow::Result<()> {
-        let temp_dir = TempDir::new("legacy_blob_test").unwrap();
-        std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
-
-        std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
-
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND_CHR,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
-            USRCERT_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
-            CACERT_AUTHBOUND,
-        )
-        .unwrap();
-
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRPKEY_non_authbound"),
-            USRPKEY_NON_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_non_authbound"),
-            USRPKEY_NON_AUTHBOUND_CHR,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRCERT_non_authbound"),
-            USRCERT_NON_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_CACERT_non_authbound"),
-            CACERT_NON_AUTHBOUND,
-        )
-        .unwrap();
-
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        if let (Some((Blob { flags, value }, _params)), Some(cert), Some(chain)) =
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
-        {
-            assert_eq!(flags, 4);
-            assert_eq!(
-                value,
-                BlobValue::Encrypted {
-                    data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
-                    iv: USRPKEY_AUTHBOUND_IV.to_vec(),
-                    tag: USRPKEY_AUTHBOUND_TAG.to_vec()
-                }
-            );
-            assert_eq!(&cert[..], LOADED_CERT_AUTHBOUND);
-            assert_eq!(&chain[..], LOADED_CACERT_AUTHBOUND);
-        } else {
-            panic!("");
-        }
-
-        if let (Some((Blob { flags, value: _ }, _params)), Some(cert), Some(chain)) =
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
-        {
-            assert_eq!(flags, 4);
-            //assert_eq!(value, BlobValue::Encrypted(..));
-            assert_eq!(&cert[..], LOADED_CERT_AUTHBOUND);
-            assert_eq!(&chain[..], LOADED_CACERT_AUTHBOUND);
-        } else {
-            panic!("");
-        }
-        if let (Some((Blob { flags, value }, _params)), Some(cert), Some(chain)) =
-            legacy_blob_loader.load_by_uid_alias(10223, "non_authbound", &None)?
-        {
-            assert_eq!(flags, 0);
-            assert_eq!(value, BlobValue::Decrypted(LOADED_USRPKEY_NON_AUTHBOUND.try_into()?));
-            assert_eq!(&cert[..], LOADED_CERT_NON_AUTHBOUND);
-            assert_eq!(&chain[..], LOADED_CACERT_NON_AUTHBOUND);
-        } else {
-            panic!("");
-        }
-
-        legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
-        legacy_blob_loader
-            .remove_keystore_entry(10223, "non_authbound")
-            .expect("This should succeed.");
-
-        assert_eq!(
-            (None, None, None),
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
-        );
-        assert_eq!(
-            (None, None, None),
-            legacy_blob_loader.load_by_uid_alias(10223, "non_authbound", &None)?
-        );
-
-        // The database should not be empty due to the super key.
-        assert!(!legacy_blob_loader.is_empty()?);
-        assert!(!legacy_blob_loader.is_empty_user(0)?);
-
-        // The database should be considered empty for user 1.
-        assert!(legacy_blob_loader.is_empty_user(1)?);
-
-        legacy_blob_loader.remove_super_key(0);
-
-        // Now it should be empty.
-        assert!(legacy_blob_loader.is_empty_user(0)?);
-        assert!(legacy_blob_loader.is_empty()?);
-
-        Ok(())
-    }
-
-    struct TestKey(ZVec);
-
-    impl crate::utils::AesGcmKey for TestKey {
-        fn key(&self) -> &[u8] {
-            &self.0
-        }
-    }
-
-    impl Deref for TestKey {
-        type Target = [u8];
-        fn deref(&self) -> &Self::Target {
-            &self.0
-        }
-    }
-
-    #[test]
-    fn test_with_encrypted_characteristics() -> anyhow::Result<()> {
-        let temp_dir = TempDir::new("test_with_encrypted_characteristics").unwrap();
-        std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
-
-        let pw: Password = PASSWORD.into();
-        let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
-        let super_key =
-            Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
-
-        std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
-
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND,
-        )
-        .unwrap();
-        make_encrypted_characteristics_file(
-            &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
-            &super_key,
-            KEY_PARAMETERS,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
-            USRCERT_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
-            CACERT_AUTHBOUND,
-        )
-        .unwrap();
-
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        assert_eq!(
-            legacy_blob_loader
-                .load_by_uid_alias(10223, "authbound", &None)
-                .unwrap_err()
-                .root_cause()
-                .downcast_ref::<Error>(),
-            Some(&Error::LockedComponent)
-        );
-
-        assert_eq!(
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &Some(super_key)).unwrap(),
-            (
-                Some((
-                    Blob {
-                        flags: 4,
-                        value: BlobValue::Encrypted {
-                            data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
-                            iv: USRPKEY_AUTHBOUND_IV.to_vec(),
-                            tag: USRPKEY_AUTHBOUND_TAG.to_vec()
-                        }
-                    },
-                    structured_test_params()
-                )),
-                Some(LOADED_CERT_AUTHBOUND.to_vec()),
-                Some(LOADED_CACERT_AUTHBOUND.to_vec())
-            )
-        );
-
-        legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
-
-        assert_eq!(
-            (None, None, None),
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None).unwrap()
-        );
-
-        // The database should not be empty due to the super key.
-        assert!(!legacy_blob_loader.is_empty().unwrap());
-        assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
-
-        // The database should be considered empty for user 1.
-        assert!(legacy_blob_loader.is_empty_user(1).unwrap());
-
-        legacy_blob_loader.remove_super_key(0);
-
-        // Now it should be empty.
-        assert!(legacy_blob_loader.is_empty_user(0).unwrap());
-        assert!(legacy_blob_loader.is_empty().unwrap());
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_with_encrypted_certificates() -> anyhow::Result<()> {
-        let temp_dir = TempDir::new("test_with_encrypted_certificates").unwrap();
-        std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
-
-        let pw: Password = PASSWORD.into();
-        let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
-        let super_key =
-            Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
-
-        std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
-
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND_CHR,
-        )
-        .unwrap();
-        make_encrypted_usr_cert_file(
-            &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
-            &super_key,
-            LOADED_CERT_AUTHBOUND,
-        )
-        .unwrap();
-        make_encrypted_ca_cert_file(
-            &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
-            &super_key,
-            LOADED_CACERT_AUTHBOUND,
-        )
-        .unwrap();
-
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        assert_eq!(
-            legacy_blob_loader
-                .load_by_uid_alias(10223, "authbound", &None)
-                .unwrap_err()
-                .root_cause()
-                .downcast_ref::<Error>(),
-            Some(&Error::LockedComponent)
-        );
-
-        assert_eq!(
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &Some(super_key)).unwrap(),
-            (
-                Some((
-                    Blob {
-                        flags: 4,
-                        value: BlobValue::Encrypted {
-                            data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
-                            iv: USRPKEY_AUTHBOUND_IV.to_vec(),
-                            tag: USRPKEY_AUTHBOUND_TAG.to_vec()
-                        }
-                    },
-                    structured_test_params_cache()
-                )),
-                Some(LOADED_CERT_AUTHBOUND.to_vec()),
-                Some(LOADED_CACERT_AUTHBOUND.to_vec())
-            )
-        );
-
-        legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
-
-        assert_eq!(
-            (None, None, None),
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None).unwrap()
-        );
-
-        // The database should not be empty due to the super key.
-        assert!(!legacy_blob_loader.is_empty().unwrap());
-        assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
-
-        // The database should be considered empty for user 1.
-        assert!(legacy_blob_loader.is_empty_user(1).unwrap());
-
-        legacy_blob_loader.remove_super_key(0);
-
-        // Now it should be empty.
-        assert!(legacy_blob_loader.is_empty_user(0).unwrap());
-        assert!(legacy_blob_loader.is_empty().unwrap());
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_in_place_key_migration() -> anyhow::Result<()> {
-        let temp_dir = TempDir::new("test_in_place_key_migration").unwrap();
-        std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
-
-        let pw: Password = PASSWORD.into();
-        let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
-        let super_key =
-            Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
-
-        std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
-
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND,
-        )
-        .unwrap();
-        std::fs::write(
-            &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
-            USRPKEY_AUTHBOUND_CHR,
-        )
-        .unwrap();
-        make_encrypted_usr_cert_file(
-            &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
-            &super_key,
-            LOADED_CERT_AUTHBOUND,
-        )
-        .unwrap();
-        make_encrypted_ca_cert_file(
-            &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
-            &super_key,
-            LOADED_CACERT_AUTHBOUND,
-        )
-        .unwrap();
-
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        assert_eq!(
-            legacy_blob_loader
-                .load_by_uid_alias(10223, "authbound", &None)
-                .unwrap_err()
-                .root_cause()
-                .downcast_ref::<Error>(),
-            Some(&Error::LockedComponent)
-        );
-
-        let super_key: Option<Arc<dyn AesGcm>> = Some(super_key);
-
-        assert_eq!(
-            legacy_blob_loader.load_by_uid_alias(10223, "authbound", &super_key).unwrap(),
-            (
-                Some((
-                    Blob {
-                        flags: 4,
-                        value: BlobValue::Encrypted {
-                            data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
-                            iv: USRPKEY_AUTHBOUND_IV.to_vec(),
-                            tag: USRPKEY_AUTHBOUND_TAG.to_vec()
-                        }
-                    },
-                    structured_test_params_cache()
-                )),
-                Some(LOADED_CERT_AUTHBOUND.to_vec()),
-                Some(LOADED_CACERT_AUTHBOUND.to_vec())
-            )
-        );
-
-        legacy_blob_loader.move_keystore_entry(10223, 10224, "authbound", "boundauth").unwrap();
-
-        assert_eq!(
-            legacy_blob_loader
-                .load_by_uid_alias(10224, "boundauth", &None)
-                .unwrap_err()
-                .root_cause()
-                .downcast_ref::<Error>(),
-            Some(&Error::LockedComponent)
-        );
-
-        assert_eq!(
-            legacy_blob_loader.load_by_uid_alias(10224, "boundauth", &super_key).unwrap(),
-            (
-                Some((
-                    Blob {
-                        flags: 4,
-                        value: BlobValue::Encrypted {
-                            data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
-                            iv: USRPKEY_AUTHBOUND_IV.to_vec(),
-                            tag: USRPKEY_AUTHBOUND_TAG.to_vec()
-                        }
-                    },
-                    structured_test_params_cache()
-                )),
-                Some(LOADED_CERT_AUTHBOUND.to_vec()),
-                Some(LOADED_CACERT_AUTHBOUND.to_vec())
-            )
-        );
-
-        legacy_blob_loader.remove_keystore_entry(10224, "boundauth").expect("This should succeed.");
-
-        assert_eq!(
-            (None, None, None),
-            legacy_blob_loader.load_by_uid_alias(10224, "boundauth", &None).unwrap()
-        );
-
-        // The database should not be empty due to the super key.
-        assert!(!legacy_blob_loader.is_empty().unwrap());
-        assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
-
-        // The database should be considered empty for user 1.
-        assert!(legacy_blob_loader.is_empty_user(1).unwrap());
-
-        legacy_blob_loader.remove_super_key(0);
-
-        // Now it should be empty.
-        assert!(legacy_blob_loader.is_empty_user(0).unwrap());
-        assert!(legacy_blob_loader.is_empty().unwrap());
-
-        Ok(())
-    }
-
-    #[test]
-    fn list_non_existing_user() -> Result<()> {
-        let temp_dir = TempDir::new("list_non_existing_user").unwrap();
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        assert!(legacy_blob_loader.list_user(20)?.is_empty());
-
-        Ok(())
-    }
-
-    #[test]
-    fn list_legacy_keystore_entries_on_non_existing_user() -> Result<()> {
-        let temp_dir = TempDir::new("list_legacy_keystore_entries_on_non_existing_user").unwrap();
-        let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
-
-        assert!(legacy_blob_loader.list_legacy_keystore_entries_for_user(20)?.is_empty());
-
-        Ok(())
-    }
-
-    #[test]
-    fn test_move_keystore_entry() {
-        let temp_dir = TempDir::new("test_move_keystore_entry").unwrap();
-        std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
-
-        const SOME_CONTENT: &[u8] = b"some content";
-        const ANOTHER_CONTENT: &[u8] = b"another content";
-        const SOME_FILENAME: &str = "some_file";
-        const ANOTHER_FILENAME: &str = "another_file";
-
-        std::fs::write(&*temp_dir.build().push("user_0").push(SOME_FILENAME), SOME_CONTENT)
-            .unwrap();
-
-        std::fs::write(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME), ANOTHER_CONTENT)
-            .unwrap();
-
-        // Non existent source id silently ignored.
-        assert!(LegacyBlobLoader::move_keystore_file_if_exists(
-            1,
-            2,
-            "non_existent",
-            ANOTHER_FILENAME,
-            "ignored",
-            |_, alias, _| temp_dir.build().push("user_0").push(alias).to_path_buf()
-        )
-        .is_ok());
-
-        // Content of another_file has not changed.
-        let another_content =
-            std::fs::read(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME)).unwrap();
-        assert_eq!(&another_content, ANOTHER_CONTENT);
-
-        // Check that some_file still exists.
-        assert!(temp_dir.build().push("user_0").push(SOME_FILENAME).exists());
-        // Existing target files are silently overwritten.
-
-        assert!(LegacyBlobLoader::move_keystore_file_if_exists(
-            1,
-            2,
-            SOME_FILENAME,
-            ANOTHER_FILENAME,
-            "ignored",
-            |_, alias, _| temp_dir.build().push("user_0").push(alias).to_path_buf()
-        )
-        .is_ok());
-
-        // Content of another_file is now "some content".
-        let another_content =
-            std::fs::read(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME)).unwrap();
-        assert_eq!(&another_content, SOME_CONTENT);
-
-        // Check that some_file no longer exists.
-        assert!(!temp_dir.build().push("user_0").push(SOME_FILENAME).exists());
-    }
-}
diff --git a/keystore2/src/legacy_blob/tests.rs b/keystore2/src/legacy_blob/tests.rs
new file mode 100644
index 0000000..53fe03f
--- /dev/null
+++ b/keystore2/src/legacy_blob/tests.rs
@@ -0,0 +1,676 @@
+// 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.
+
+//! Tests for legacy keyblob processing.
+
+#![allow(dead_code)]
+use super::*;
+use crate::legacy_blob::test_utils::legacy_blob_test_vectors::*;
+use crate::legacy_blob::test_utils::*;
+use anyhow::{anyhow, Result};
+use keystore2_crypto::aes_gcm_decrypt;
+use keystore2_test_utils::TempDir;
+use rand::Rng;
+use std::convert::TryInto;
+use std::ops::Deref;
+use std::string::FromUtf8Error;
+
+#[test]
+fn decode_encode_alias_test() {
+    static ALIAS: &str = "#({}test[])😗";
+    static ENCODED_ALIAS: &str = "+S+X{}test[]+Y.`-O-H-G";
+    // Second multi byte out of range ------v
+    static ENCODED_ALIAS_ERROR1: &str = "+S+{}test[]+Y";
+    // Incomplete multi byte ------------------------v
+    static ENCODED_ALIAS_ERROR2: &str = "+S+X{}test[]+";
+    // Our encoding: ".`-O-H-G"
+    // is UTF-8: 0xF0 0x9F 0x98 0x97
+    // is UNICODE: U+1F617
+    // is 😗
+    // But +H below is a valid encoding for 0x18 making this sequence invalid UTF-8.
+    static ENCODED_ALIAS_ERROR_UTF8: &str = ".`-O+H-G";
+
+    assert_eq!(ENCODED_ALIAS, &LegacyBlobLoader::encode_alias(ALIAS));
+    assert_eq!(ALIAS, &LegacyBlobLoader::decode_alias(ENCODED_ALIAS).unwrap());
+    assert_eq!(
+        Some(&Error::BadEncoding),
+        LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR1)
+            .unwrap_err()
+            .root_cause()
+            .downcast_ref::<Error>()
+    );
+    assert_eq!(
+        Some(&Error::BadEncoding),
+        LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR2)
+            .unwrap_err()
+            .root_cause()
+            .downcast_ref::<Error>()
+    );
+    assert!(LegacyBlobLoader::decode_alias(ENCODED_ALIAS_ERROR_UTF8)
+        .unwrap_err()
+        .root_cause()
+        .downcast_ref::<FromUtf8Error>()
+        .is_some());
+
+    for _i in 0..100 {
+        // Any valid UTF-8 string should be en- and decoded without loss.
+        let alias_str = rand::thread_rng().gen::<[char; 20]>().iter().collect::<String>();
+        let random_alias = alias_str.as_bytes();
+        let encoded = LegacyBlobLoader::encode_alias(&alias_str);
+        let decoded = match LegacyBlobLoader::decode_alias(&encoded) {
+            Ok(d) => d,
+            Err(_) => panic!("random_alias: {:x?}\nencoded {}", random_alias, encoded),
+        };
+        assert_eq!(random_alias.to_vec(), decoded.bytes().collect::<Vec<u8>>());
+    }
+}
+
+#[test]
+fn read_golden_key_blob_test() -> anyhow::Result<()> {
+    let blob = LegacyBlobLoader::new_from_stream_decrypt_with(&mut &*BLOB, |_, _, _, _, _| {
+        Err(anyhow!("should not be called"))
+    })
+    .unwrap();
+    assert!(!blob.is_encrypted());
+    assert!(!blob.is_fallback());
+    assert!(!blob.is_strongbox());
+    assert!(!blob.is_critical_to_device_encryption());
+    assert_eq!(blob.value(), &BlobValue::Generic([0xde, 0xed, 0xbe, 0xef].to_vec()));
+
+    let blob =
+        LegacyBlobLoader::new_from_stream_decrypt_with(&mut &*REAL_LEGACY_BLOB, |_, _, _, _, _| {
+            Err(anyhow!("should not be called"))
+        })
+        .unwrap();
+    assert!(!blob.is_encrypted());
+    assert!(!blob.is_fallback());
+    assert!(!blob.is_strongbox());
+    assert!(!blob.is_critical_to_device_encryption());
+    assert_eq!(blob.value(), &BlobValue::Decrypted(REAL_LEGACY_BLOB_PAYLOAD.try_into().unwrap()));
+    Ok(())
+}
+
+#[test]
+fn read_aes_gcm_encrypted_key_blob_test() {
+    let blob = LegacyBlobLoader::new_from_stream_decrypt_with(
+        &mut &*AES_GCM_ENCRYPTED_BLOB,
+        |d, iv, tag, salt, key_size| {
+            assert_eq!(salt, None);
+            assert_eq!(key_size, None);
+            assert_eq!(
+                iv,
+                &[
+                    0xbd, 0xdb, 0x8d, 0x69, 0x72, 0x56, 0xf0, 0xf5, 0xa4, 0x02, 0x88, 0x7f, 0x00,
+                    0x00, 0x00, 0x00,
+                ]
+            );
+            assert_eq!(
+                tag,
+                &[
+                    0x50, 0xd9, 0x97, 0x95, 0x37, 0x6e, 0x28, 0x6a, 0x28, 0x9d, 0x51, 0xb9, 0xb9,
+                    0xe0, 0x0b, 0xc3
+                ][..]
+            );
+            aes_gcm_decrypt(d, iv, tag, AES_KEY).context("Trying to decrypt blob.")
+        },
+    )
+    .unwrap();
+    assert!(blob.is_encrypted());
+    assert!(!blob.is_fallback());
+    assert!(!blob.is_strongbox());
+    assert!(!blob.is_critical_to_device_encryption());
+
+    assert_eq!(blob.value(), &BlobValue::Decrypted(DECRYPTED_PAYLOAD.try_into().unwrap()));
+}
+
+#[test]
+fn read_golden_key_blob_too_short_test() {
+    let error =
+        LegacyBlobLoader::new_from_stream_decrypt_with(&mut &BLOB[0..15], |_, _, _, _, _| {
+            Err(anyhow!("should not be called"))
+        })
+        .unwrap_err();
+    assert_eq!(Some(&Error::BadLen), error.root_cause().downcast_ref::<Error>());
+}
+
+#[test]
+fn test_is_empty() {
+    let temp_dir = TempDir::new("test_is_empty").expect("Failed to create temp dir.");
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    assert!(legacy_blob_loader.is_empty().expect("Should succeed and be empty."));
+
+    let _db =
+        crate::database::KeystoreDB::new(temp_dir.path(), None).expect("Failed to open database.");
+
+    assert!(legacy_blob_loader.is_empty().expect("Should succeed and still be empty."));
+
+    std::fs::create_dir(&*temp_dir.build().push("user_0")).expect("Failed to create user_0.");
+
+    assert!(!legacy_blob_loader.is_empty().expect("Should succeed but not be empty."));
+
+    std::fs::create_dir(&*temp_dir.build().push("user_10")).expect("Failed to create user_10.");
+
+    assert!(!legacy_blob_loader.is_empty().expect("Should succeed but still not be empty."));
+
+    std::fs::remove_dir_all(&*temp_dir.build().push("user_0")).expect("Failed to remove user_0.");
+
+    assert!(!legacy_blob_loader.is_empty().expect("Should succeed but still not be empty."));
+
+    std::fs::remove_dir_all(&*temp_dir.build().push("user_10")).expect("Failed to remove user_10.");
+
+    assert!(legacy_blob_loader.is_empty().expect("Should succeed and be empty again."));
+}
+
+#[test]
+fn test_legacy_blobs() -> anyhow::Result<()> {
+    let temp_dir = TempDir::new("legacy_blob_test").unwrap();
+    std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
+
+    std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
+
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND_CHR,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
+        USRCERT_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
+        CACERT_AUTHBOUND,
+    )
+    .unwrap();
+
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRPKEY_non_authbound"),
+        USRPKEY_NON_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_non_authbound"),
+        USRPKEY_NON_AUTHBOUND_CHR,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRCERT_non_authbound"),
+        USRCERT_NON_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_CACERT_non_authbound"),
+        CACERT_NON_AUTHBOUND,
+    )
+    .unwrap();
+
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    if let (Some((Blob { flags, value }, _params)), Some(cert), Some(chain)) =
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
+    {
+        assert_eq!(flags, 4);
+        assert_eq!(
+            value,
+            BlobValue::Encrypted {
+                data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
+                iv: USRPKEY_AUTHBOUND_IV.to_vec(),
+                tag: USRPKEY_AUTHBOUND_TAG.to_vec()
+            }
+        );
+        assert_eq!(&cert[..], LOADED_CERT_AUTHBOUND);
+        assert_eq!(&chain[..], LOADED_CACERT_AUTHBOUND);
+    } else {
+        panic!("");
+    }
+
+    if let (Some((Blob { flags, value: _ }, _params)), Some(cert), Some(chain)) =
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
+    {
+        assert_eq!(flags, 4);
+        //assert_eq!(value, BlobValue::Encrypted(..));
+        assert_eq!(&cert[..], LOADED_CERT_AUTHBOUND);
+        assert_eq!(&chain[..], LOADED_CACERT_AUTHBOUND);
+    } else {
+        panic!("");
+    }
+    if let (Some((Blob { flags, value }, _params)), Some(cert), Some(chain)) =
+        legacy_blob_loader.load_by_uid_alias(10223, "non_authbound", &None)?
+    {
+        assert_eq!(flags, 0);
+        assert_eq!(value, BlobValue::Decrypted(LOADED_USRPKEY_NON_AUTHBOUND.try_into()?));
+        assert_eq!(&cert[..], LOADED_CERT_NON_AUTHBOUND);
+        assert_eq!(&chain[..], LOADED_CACERT_NON_AUTHBOUND);
+    } else {
+        panic!("");
+    }
+
+    legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
+    legacy_blob_loader.remove_keystore_entry(10223, "non_authbound").expect("This should succeed.");
+
+    assert_eq!(
+        (None, None, None),
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None)?
+    );
+    assert_eq!(
+        (None, None, None),
+        legacy_blob_loader.load_by_uid_alias(10223, "non_authbound", &None)?
+    );
+
+    // The database should not be empty due to the super key.
+    assert!(!legacy_blob_loader.is_empty()?);
+    assert!(!legacy_blob_loader.is_empty_user(0)?);
+
+    // The database should be considered empty for user 1.
+    assert!(legacy_blob_loader.is_empty_user(1)?);
+
+    legacy_blob_loader.remove_super_key(0);
+
+    // Now it should be empty.
+    assert!(legacy_blob_loader.is_empty_user(0)?);
+    assert!(legacy_blob_loader.is_empty()?);
+
+    Ok(())
+}
+
+struct TestKey(ZVec);
+
+impl crate::utils::AesGcmKey for TestKey {
+    fn key(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+impl Deref for TestKey {
+    type Target = [u8];
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+#[test]
+fn test_with_encrypted_characteristics() -> anyhow::Result<()> {
+    let temp_dir = TempDir::new("test_with_encrypted_characteristics").unwrap();
+    std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
+
+    let pw: Password = PASSWORD.into();
+    let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
+    let super_key =
+        Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
+
+    std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
+
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND,
+    )
+    .unwrap();
+    make_encrypted_characteristics_file(
+        &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
+        &super_key,
+        KEY_PARAMETERS,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
+        USRCERT_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
+        CACERT_AUTHBOUND,
+    )
+    .unwrap();
+
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    assert_eq!(
+        legacy_blob_loader
+            .load_by_uid_alias(10223, "authbound", &None)
+            .unwrap_err()
+            .root_cause()
+            .downcast_ref::<Error>(),
+        Some(&Error::LockedComponent)
+    );
+
+    assert_eq!(
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &Some(super_key)).unwrap(),
+        (
+            Some((
+                Blob {
+                    flags: 4,
+                    value: BlobValue::Encrypted {
+                        data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
+                        iv: USRPKEY_AUTHBOUND_IV.to_vec(),
+                        tag: USRPKEY_AUTHBOUND_TAG.to_vec()
+                    }
+                },
+                structured_test_params()
+            )),
+            Some(LOADED_CERT_AUTHBOUND.to_vec()),
+            Some(LOADED_CACERT_AUTHBOUND.to_vec())
+        )
+    );
+
+    legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
+
+    assert_eq!(
+        (None, None, None),
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None).unwrap()
+    );
+
+    // The database should not be empty due to the super key.
+    assert!(!legacy_blob_loader.is_empty().unwrap());
+    assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
+
+    // The database should be considered empty for user 1.
+    assert!(legacy_blob_loader.is_empty_user(1).unwrap());
+
+    legacy_blob_loader.remove_super_key(0);
+
+    // Now it should be empty.
+    assert!(legacy_blob_loader.is_empty_user(0).unwrap());
+    assert!(legacy_blob_loader.is_empty().unwrap());
+
+    Ok(())
+}
+
+#[test]
+fn test_with_encrypted_certificates() -> anyhow::Result<()> {
+    let temp_dir = TempDir::new("test_with_encrypted_certificates").unwrap();
+    std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
+
+    let pw: Password = PASSWORD.into();
+    let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
+    let super_key =
+        Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
+
+    std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
+
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND_CHR,
+    )
+    .unwrap();
+    make_encrypted_usr_cert_file(
+        &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
+        &super_key,
+        LOADED_CERT_AUTHBOUND,
+    )
+    .unwrap();
+    make_encrypted_ca_cert_file(
+        &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
+        &super_key,
+        LOADED_CACERT_AUTHBOUND,
+    )
+    .unwrap();
+
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    assert_eq!(
+        legacy_blob_loader
+            .load_by_uid_alias(10223, "authbound", &None)
+            .unwrap_err()
+            .root_cause()
+            .downcast_ref::<Error>(),
+        Some(&Error::LockedComponent)
+    );
+
+    assert_eq!(
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &Some(super_key)).unwrap(),
+        (
+            Some((
+                Blob {
+                    flags: 4,
+                    value: BlobValue::Encrypted {
+                        data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
+                        iv: USRPKEY_AUTHBOUND_IV.to_vec(),
+                        tag: USRPKEY_AUTHBOUND_TAG.to_vec()
+                    }
+                },
+                structured_test_params_cache()
+            )),
+            Some(LOADED_CERT_AUTHBOUND.to_vec()),
+            Some(LOADED_CACERT_AUTHBOUND.to_vec())
+        )
+    );
+
+    legacy_blob_loader.remove_keystore_entry(10223, "authbound").expect("This should succeed.");
+
+    assert_eq!(
+        (None, None, None),
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &None).unwrap()
+    );
+
+    // The database should not be empty due to the super key.
+    assert!(!legacy_blob_loader.is_empty().unwrap());
+    assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
+
+    // The database should be considered empty for user 1.
+    assert!(legacy_blob_loader.is_empty_user(1).unwrap());
+
+    legacy_blob_loader.remove_super_key(0);
+
+    // Now it should be empty.
+    assert!(legacy_blob_loader.is_empty_user(0).unwrap());
+    assert!(legacy_blob_loader.is_empty().unwrap());
+
+    Ok(())
+}
+
+#[test]
+fn test_in_place_key_migration() -> anyhow::Result<()> {
+    let temp_dir = TempDir::new("test_in_place_key_migration").unwrap();
+    std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
+
+    let pw: Password = PASSWORD.into();
+    let pw_key = TestKey(pw.derive_key_pbkdf2(SUPERKEY_SALT, 32).unwrap());
+    let super_key =
+        Arc::new(TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap()));
+
+    std::fs::write(&*temp_dir.build().push("user_0").push(".masterkey"), SUPERKEY).unwrap();
+
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push("10223_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND,
+    )
+    .unwrap();
+    std::fs::write(
+        &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
+        USRPKEY_AUTHBOUND_CHR,
+    )
+    .unwrap();
+    make_encrypted_usr_cert_file(
+        &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
+        &super_key,
+        LOADED_CERT_AUTHBOUND,
+    )
+    .unwrap();
+    make_encrypted_ca_cert_file(
+        &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
+        &super_key,
+        LOADED_CACERT_AUTHBOUND,
+    )
+    .unwrap();
+
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    assert_eq!(
+        legacy_blob_loader
+            .load_by_uid_alias(10223, "authbound", &None)
+            .unwrap_err()
+            .root_cause()
+            .downcast_ref::<Error>(),
+        Some(&Error::LockedComponent)
+    );
+
+    let super_key: Option<Arc<dyn AesGcm>> = Some(super_key);
+
+    assert_eq!(
+        legacy_blob_loader.load_by_uid_alias(10223, "authbound", &super_key).unwrap(),
+        (
+            Some((
+                Blob {
+                    flags: 4,
+                    value: BlobValue::Encrypted {
+                        data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
+                        iv: USRPKEY_AUTHBOUND_IV.to_vec(),
+                        tag: USRPKEY_AUTHBOUND_TAG.to_vec()
+                    }
+                },
+                structured_test_params_cache()
+            )),
+            Some(LOADED_CERT_AUTHBOUND.to_vec()),
+            Some(LOADED_CACERT_AUTHBOUND.to_vec())
+        )
+    );
+
+    legacy_blob_loader.move_keystore_entry(10223, 10224, "authbound", "boundauth").unwrap();
+
+    assert_eq!(
+        legacy_blob_loader
+            .load_by_uid_alias(10224, "boundauth", &None)
+            .unwrap_err()
+            .root_cause()
+            .downcast_ref::<Error>(),
+        Some(&Error::LockedComponent)
+    );
+
+    assert_eq!(
+        legacy_blob_loader.load_by_uid_alias(10224, "boundauth", &super_key).unwrap(),
+        (
+            Some((
+                Blob {
+                    flags: 4,
+                    value: BlobValue::Encrypted {
+                        data: USRPKEY_AUTHBOUND_ENC_PAYLOAD.to_vec(),
+                        iv: USRPKEY_AUTHBOUND_IV.to_vec(),
+                        tag: USRPKEY_AUTHBOUND_TAG.to_vec()
+                    }
+                },
+                structured_test_params_cache()
+            )),
+            Some(LOADED_CERT_AUTHBOUND.to_vec()),
+            Some(LOADED_CACERT_AUTHBOUND.to_vec())
+        )
+    );
+
+    legacy_blob_loader.remove_keystore_entry(10224, "boundauth").expect("This should succeed.");
+
+    assert_eq!(
+        (None, None, None),
+        legacy_blob_loader.load_by_uid_alias(10224, "boundauth", &None).unwrap()
+    );
+
+    // The database should not be empty due to the super key.
+    assert!(!legacy_blob_loader.is_empty().unwrap());
+    assert!(!legacy_blob_loader.is_empty_user(0).unwrap());
+
+    // The database should be considered empty for user 1.
+    assert!(legacy_blob_loader.is_empty_user(1).unwrap());
+
+    legacy_blob_loader.remove_super_key(0);
+
+    // Now it should be empty.
+    assert!(legacy_blob_loader.is_empty_user(0).unwrap());
+    assert!(legacy_blob_loader.is_empty().unwrap());
+
+    Ok(())
+}
+
+#[test]
+fn list_non_existing_user() -> Result<()> {
+    let temp_dir = TempDir::new("list_non_existing_user").unwrap();
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    assert!(legacy_blob_loader.list_user(20)?.is_empty());
+
+    Ok(())
+}
+
+#[test]
+fn list_legacy_keystore_entries_on_non_existing_user() -> Result<()> {
+    let temp_dir = TempDir::new("list_legacy_keystore_entries_on_non_existing_user").unwrap();
+    let legacy_blob_loader = LegacyBlobLoader::new(temp_dir.path());
+
+    assert!(legacy_blob_loader.list_legacy_keystore_entries_for_user(20)?.is_empty());
+
+    Ok(())
+}
+
+#[test]
+fn test_move_keystore_entry() {
+    let temp_dir = TempDir::new("test_move_keystore_entry").unwrap();
+    std::fs::create_dir(&*temp_dir.build().push("user_0")).unwrap();
+
+    const SOME_CONTENT: &[u8] = b"some content";
+    const ANOTHER_CONTENT: &[u8] = b"another content";
+    const SOME_FILENAME: &str = "some_file";
+    const ANOTHER_FILENAME: &str = "another_file";
+
+    std::fs::write(&*temp_dir.build().push("user_0").push(SOME_FILENAME), SOME_CONTENT).unwrap();
+
+    std::fs::write(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME), ANOTHER_CONTENT)
+        .unwrap();
+
+    // Non existent source id silently ignored.
+    assert!(LegacyBlobLoader::move_keystore_file_if_exists(
+        1,
+        2,
+        "non_existent",
+        ANOTHER_FILENAME,
+        "ignored",
+        |_, alias, _| temp_dir.build().push("user_0").push(alias).to_path_buf()
+    )
+    .is_ok());
+
+    // Content of another_file has not changed.
+    let another_content =
+        std::fs::read(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME)).unwrap();
+    assert_eq!(&another_content, ANOTHER_CONTENT);
+
+    // Check that some_file still exists.
+    assert!(temp_dir.build().push("user_0").push(SOME_FILENAME).exists());
+    // Existing target files are silently overwritten.
+
+    assert!(LegacyBlobLoader::move_keystore_file_if_exists(
+        1,
+        2,
+        SOME_FILENAME,
+        ANOTHER_FILENAME,
+        "ignored",
+        |_, alias, _| temp_dir.build().push("user_0").push(alias).to_path_buf()
+    )
+    .is_ok());
+
+    // Content of another_file is now "some content".
+    let another_content =
+        std::fs::read(&*temp_dir.build().push("user_0").push(ANOTHER_FILENAME)).unwrap();
+    assert_eq!(&another_content, SOME_CONTENT);
+
+    // Check that some_file no longer exists.
+    assert!(!temp_dir.build().push("user_0").push(SOME_FILENAME).exists());
+}