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/permission/tests.rs b/keystore2/src/permission/tests.rs
new file mode 100644
index 0000000..f555c12
--- /dev/null
+++ b/keystore2/src/permission/tests.rs
@@ -0,0 +1,434 @@
+// 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.
+
+//! Access control tests.
+
+use super::*;
+use crate::key_perm_set;
+use anyhow::anyhow;
+use anyhow::Result;
+use keystore2_selinux::*;
+
+const ALL_PERMS: KeyPermSet = key_perm_set![
+    KeyPerm::ManageBlob,
+    KeyPerm::Delete,
+    KeyPerm::UseDevId,
+    KeyPerm::ReqForcedOp,
+    KeyPerm::GenUniqueId,
+    KeyPerm::Grant,
+    KeyPerm::GetInfo,
+    KeyPerm::Rebind,
+    KeyPerm::Update,
+    KeyPerm::Use,
+    KeyPerm::ConvertStorageKeyToEphemeral,
+];
+
+const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
+    KeyPerm::Delete,
+    KeyPerm::UseDevId,
+    // No KeyPerm::Grant
+    KeyPerm::GetInfo,
+    KeyPerm::Rebind,
+    KeyPerm::Update,
+    KeyPerm::Use,
+];
+
+const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
+    KeyPerm::ManageBlob,
+    KeyPerm::Delete,
+    KeyPerm::UseDevId,
+    KeyPerm::ReqForcedOp,
+    KeyPerm::GenUniqueId,
+    // No KeyPerm::Grant
+    KeyPerm::GetInfo,
+    KeyPerm::Rebind,
+    KeyPerm::Update,
+    KeyPerm::Use,
+    KeyPerm::ConvertStorageKeyToEphemeral,
+];
+
+const UNPRIV_PERMS: KeyPermSet = key_perm_set![
+    KeyPerm::Delete,
+    KeyPerm::GetInfo,
+    KeyPerm::Rebind,
+    KeyPerm::Update,
+    KeyPerm::Use,
+];
+
+/// The su_key namespace as defined in su.te and keystore_key_contexts of the
+/// SePolicy (system/sepolicy).
+const SU_KEY_NAMESPACE: i32 = 0;
+/// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+/// SePolicy (system/sepolicy).
+const SHELL_KEY_NAMESPACE: i32 = 1;
+
+pub fn test_getcon() -> Result<Context> {
+    Context::new("u:object_r:keystore:s0")
+}
+
+// This macro evaluates the given expression and checks that
+// a) evaluated to Result::Err() and that
+// b) the wrapped error is selinux::Error::perm() (permission denied).
+// We use a macro here because a function would mask which invocation caused the failure.
+//
+// TODO b/164121720 Replace this macro with a function when `track_caller` is available.
+macro_rules! assert_perm_failed {
+    ($test_function:expr) => {
+        let result = $test_function;
+        assert!(result.is_err(), "Permission check should have failed.");
+        assert_eq!(
+            Some(&selinux::Error::perm()),
+            result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
+        );
+    };
+}
+
+fn check_context() -> Result<(selinux::Context, i32, bool)> {
+    // Calling the non mocked selinux::getcon here intended.
+    let context = selinux::getcon()?;
+    match context.to_str().unwrap() {
+        "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+        "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+        c => Err(anyhow!(format!(
+            "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+            c
+        ))),
+    }
+}
+
+#[test]
+fn check_keystore_permission_test() -> Result<()> {
+    let system_server_ctx = Context::new("u:r:system_server:s0")?;
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::AddAuth).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearNs).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Lock).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Reset).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Unlock).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangeUser).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangePassword).is_ok());
+    assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearUID).is_ok());
+    let shell_ctx = Context::new("u:r:shell:s0")?;
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::AddAuth));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearNs));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::List));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Lock));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Reset));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Unlock));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangeUser));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangePassword));
+    assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearUID));
+    Ok(())
+}
+
+#[test]
+fn check_grant_permission_app() -> Result<()> {
+    let system_server_ctx = Context::new("u:r:system_server:s0")?;
+    let shell_ctx = Context::new("u:r:shell:s0")?;
+    let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
+    check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
+        .expect("Grant permission check failed.");
+
+    // attempts to grant the grant permission must always fail even when privileged.
+    assert_perm_failed!(check_grant_permission(&system_server_ctx, KeyPerm::Grant.into(), &key));
+    // unprivileged grant attempts always fail. shell does not have the grant permission.
+    assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
+    Ok(())
+}
+
+#[test]
+fn check_grant_permission_selinux() -> Result<()> {
+    let (sctx, namespace, is_su) = check_context()?;
+    let key = KeyDescriptor {
+        domain: Domain::SELINUX,
+        nspace: namespace as i64,
+        alias: None,
+        blob: None,
+    };
+    if is_su {
+        assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
+        // attempts to grant the grant permission must always fail even when privileged.
+        assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::Grant.into(), &key));
+    } else {
+        // unprivileged grant attempts always fail. shell does not have the grant permission.
+        assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
+    }
+    Ok(())
+}
+
+#[test]
+fn check_key_permission_domain_grant() -> Result<()> {
+    let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
+
+    assert_perm_failed!(check_key_permission(
+        0,
+        &selinux::Context::new("ignored").unwrap(),
+        KeyPerm::Grant,
+        &key,
+        &Some(UNPRIV_PERMS)
+    ));
+
+    check_key_permission(
+        0,
+        &selinux::Context::new("ignored").unwrap(),
+        KeyPerm::Use,
+        &key,
+        &Some(ALL_PERMS),
+    )
+}
+
+#[test]
+fn check_key_permission_domain_app() -> Result<()> {
+    let system_server_ctx = Context::new("u:r:system_server:s0")?;
+    let shell_ctx = Context::new("u:r:shell:s0")?;
+    let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
+
+    let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
+
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
+    assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
+    assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
+
+    assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
+    assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
+    assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
+    assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
+    assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
+    assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::Grant, &key, &None));
+    assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
+    assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
+    assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
+    assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
+
+    // Also make sure that the permission fails if the caller is not the owner.
+    assert_perm_failed!(check_key_permission(
+        1, // the owner is 0
+        &system_server_ctx,
+        KeyPerm::Use,
+        &key,
+        &None
+    ));
+    // Unless there was a grant.
+    assert!(check_key_permission(
+        1,
+        &system_server_ctx,
+        KeyPerm::Use,
+        &key,
+        &Some(key_perm_set![KeyPerm::Use])
+    )
+    .is_ok());
+    // But fail if the grant did not cover the requested permission.
+    assert_perm_failed!(check_key_permission(
+        1,
+        &system_server_ctx,
+        KeyPerm::Use,
+        &key,
+        &Some(key_perm_set![KeyPerm::GetInfo])
+    ));
+
+    Ok(())
+}
+
+#[test]
+fn check_key_permission_domain_selinux() -> Result<()> {
+    let (sctx, namespace, is_su) = check_context()?;
+    let key = KeyDescriptor {
+        domain: Domain::SELINUX,
+        nspace: namespace as i64,
+        alias: None,
+        blob: None,
+    };
+
+    assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
+    assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
+    assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
+    assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
+    assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
+
+    if is_su {
+        assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
+        assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
+        assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
+        assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
+        assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
+    } else {
+        assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
+        assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
+        assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
+        assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
+        assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
+    }
+    Ok(())
+}
+
+#[test]
+fn check_key_permission_domain_blob() -> Result<()> {
+    let (sctx, namespace, is_su) = check_context()?;
+    let key =
+        KeyDescriptor { domain: Domain::BLOB, nspace: namespace as i64, alias: None, blob: None };
+
+    if is_su {
+        check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
+    } else {
+        assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
+        Ok(())
+    }
+}
+
+#[test]
+fn check_key_permission_domain_key_id() -> Result<()> {
+    let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
+
+    assert_eq!(
+        Some(&KsError::sys()),
+        check_key_permission(
+            0,
+            &selinux::Context::new("ignored").unwrap(),
+            KeyPerm::Use,
+            &key,
+            &None
+        )
+        .err()
+        .unwrap()
+        .root_cause()
+        .downcast_ref::<KsError>()
+    );
+    Ok(())
+}
+
+#[test]
+fn key_perm_set_all_test() {
+    let v = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::UseDevId,
+        KeyPerm::ReqForcedOp,
+        KeyPerm::GenUniqueId,
+        KeyPerm::Grant,
+        KeyPerm::GetInfo,
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
+    ];
+    let mut i = v.into_iter();
+    assert_eq!(i.next().unwrap().name(), "delete");
+    assert_eq!(i.next().unwrap().name(), "gen_unique_id");
+    assert_eq!(i.next().unwrap().name(), "get_info");
+    assert_eq!(i.next().unwrap().name(), "grant");
+    assert_eq!(i.next().unwrap().name(), "manage_blob");
+    assert_eq!(i.next().unwrap().name(), "rebind");
+    assert_eq!(i.next().unwrap().name(), "req_forced_op");
+    assert_eq!(i.next().unwrap().name(), "update");
+    assert_eq!(i.next().unwrap().name(), "use");
+    assert_eq!(i.next().unwrap().name(), "use_dev_id");
+    assert_eq!(None, i.next());
+}
+#[test]
+fn key_perm_set_sparse_test() {
+    let v = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::ReqForcedOp,
+        KeyPerm::GenUniqueId,
+        KeyPerm::Update,
+        KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
+    ];
+    let mut i = v.into_iter();
+    assert_eq!(i.next().unwrap().name(), "gen_unique_id");
+    assert_eq!(i.next().unwrap().name(), "manage_blob");
+    assert_eq!(i.next().unwrap().name(), "req_forced_op");
+    assert_eq!(i.next().unwrap().name(), "update");
+    assert_eq!(i.next().unwrap().name(), "use");
+    assert_eq!(None, i.next());
+}
+#[test]
+fn key_perm_set_empty_test() {
+    let v = key_perm_set![];
+    let mut i = v.into_iter();
+    assert_eq!(None, i.next());
+}
+#[test]
+fn key_perm_set_include_subset_test() {
+    let v1 = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::UseDevId,
+        KeyPerm::ReqForcedOp,
+        KeyPerm::GenUniqueId,
+        KeyPerm::Grant,
+        KeyPerm::GetInfo,
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use,
+    ];
+    let v2 = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use,
+    ];
+    assert!(v1.includes(v2));
+    assert!(!v2.includes(v1));
+}
+#[test]
+fn key_perm_set_include_equal_test() {
+    let v1 = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use,
+    ];
+    let v2 = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use,
+    ];
+    assert!(v1.includes(v2));
+    assert!(v2.includes(v1));
+}
+#[test]
+fn key_perm_set_include_overlap_test() {
+    let v1 = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::Grant, // only in v1
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use,
+    ];
+    let v2 = key_perm_set![
+        KeyPerm::ManageBlob,
+        KeyPerm::Delete,
+        KeyPerm::ReqForcedOp, // only in v2
+        KeyPerm::Rebind,
+        KeyPerm::Update,
+        KeyPerm::Use,
+    ];
+    assert!(!v1.includes(v2));
+    assert!(!v2.includes(v1));
+}
+#[test]
+fn key_perm_set_include_no_overlap_test() {
+    let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
+    let v2 = key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
+    assert!(!v1.includes(v2));
+    assert!(!v2.includes(v1));
+}