Tests updated to handle RKP-ONLY property on GSI builds.

GSI replaces the values for remote_prov_prop properties (since they’re
system_internal_prop properties), so on GSI the properties are not
reliable indicators of whether StrongBox/TEE are RKP-only or not.

Tests are updated to stop running on GSI build if generateKey API
returns `ATTESTATION_KEYS_NOT_PROVISIONED` error code when RKP_ONLY
property is undetermined.

Impacted tests: test that generates a key with attestation but doesn't provide an ATTEST_KEY,
i.e. any test that requires batch keys.

Bug: 359743897
Test: atest keystore2_client_tests
Change-Id: I8028c20a47cf46aa807270e948e37ed6a08bfa02
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index c845332..258c68f 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -38,6 +38,7 @@
 use nix::unistd::getuid;
 use std::collections::HashSet;
 use std::fmt::Write;
+use std::path::PathBuf;
 
 /// Shell namespace.
 pub const SELINUX_SHELL_NAMESPACE: i64 = 1;
@@ -50,6 +51,10 @@
 /// Vold context
 pub const TARGET_VOLD_CTX: &str = "u:r:vold:s0";
 
+const TEE_KEYMINT_RKP_ONLY: &str = "remote_provisioning.tee.rkp_only";
+
+const STRONGBOX_KEYMINT_RKP_ONLY: &str = "remote_provisioning.strongbox.rkp_only";
+
 /// Allowed tags in generated/imported key authorizations.
 /// See hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl for the
 /// list feature tags.
@@ -387,6 +392,33 @@
     })
 }
 
+/// Get the value of the given system property, if the given system property doesn't exist
+/// then returns an empty byte vector.
+pub fn get_system_prop(name: &str) -> Vec<u8> {
+    match rustutils::system_properties::read(name) {
+        Ok(Some(value)) => value.as_bytes().to_vec(),
+        _ => vec![],
+    }
+}
+
+/// Determines whether test is running on GSI.
+pub fn is_gsi() -> bool {
+    // This file is only present on GSI builds.
+    PathBuf::from("/system/system_ext/etc/init/init.gsi.rc").as_path().is_file()
+}
+
+/// Determines whether the test is on a GSI build where the rkp-only status of the device is
+/// unknown. GSI replaces the values for remote_prov_prop properties (since they’re
+/// system_internal_prop properties), so on GSI the properties are not reliable indicators of
+/// whether StrongBox/TEE is RKP-only or not.
+pub fn is_rkp_only_unknown_on_gsi(sec_level: SecurityLevel) -> bool {
+    if sec_level == SecurityLevel::TRUSTED_ENVIRONMENT {
+        is_gsi() && get_system_prop(TEE_KEYMINT_RKP_ONLY).is_empty()
+    } else {
+        is_gsi() && get_system_prop(STRONGBOX_KEYMINT_RKP_ONLY).is_empty()
+    }
+}
+
 /// Verify that given key param is listed in given authorizations list.
 pub fn check_key_param(authorizations: &[Authorization], key_param: &KeyParameter) -> bool {
     authorizations.iter().any(|auth| &auth.keyParameter == key_param)
@@ -634,7 +666,7 @@
     alias: Option<String>,
     key_params: &KeyParams,
     attest_key: Option<&KeyDescriptor>,
-) -> binder::Result<KeyMetadata> {
+) -> binder::Result<Option<KeyMetadata>> {
     let mut gen_params = AuthSetBuilder::new()
         .no_auth_required()
         .algorithm(Algorithm::RSA)
@@ -660,13 +692,29 @@
         gen_params = gen_params.attestation_challenge(value.to_vec())
     }
 
-    let key_metadata = sl.binder.generateKey(
+    let key_metadata = match sl.binder.generateKey(
         &KeyDescriptor { domain, nspace, alias, blob: None },
         attest_key,
         &gen_params,
         0,
         b"entropy",
-    )?;
+    ) {
+        Ok(metadata) => metadata,
+        Err(e) => {
+            return if is_rkp_only_unknown_on_gsi(sl.level)
+                && e.service_specific_error() == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED.0
+            {
+                // GSI replaces the values for remote_prov_prop properties (since they’re
+                // system_internal_prop properties), so on GSI the properties are not
+                // reliable indicators of whether StrongBox/TEE are RKP-only or not.
+                // Test can be skipped if it generates a key with attestation but doesn't provide
+                // an ATTEST_KEY and rkp-only property is undetermined.
+                Ok(None)
+            } else {
+                Err(e)
+            };
+        }
+    };
 
     // Must have a public key.
     assert!(key_metadata.certificate.is_some());
@@ -697,7 +745,7 @@
             }
         ));
     }
-    Ok(key_metadata)
+    Ok(Some(key_metadata))
 }
 
 /// Generate AES/3DES key.
@@ -795,12 +843,12 @@
     sl: &SecLevel,
     algorithm: Algorithm,
     att_challenge: &[u8],
-) -> binder::Result<KeyMetadata> {
+) -> binder::Result<Option<KeyMetadata>> {
     assert!(algorithm == Algorithm::RSA || algorithm == Algorithm::EC);
 
     if algorithm == Algorithm::RSA {
         let alias = "ks_rsa_attest_test_key";
-        let metadata = generate_rsa_key(
+        generate_rsa_key(
             sl,
             Domain::APP,
             -1,
@@ -816,14 +864,8 @@
             },
             None,
         )
-        .unwrap();
-        Ok(metadata)
     } else {
-        let metadata =
-            generate_ec_attestation_key(sl, att_challenge, Digest::SHA_2_256, EcCurve::P_256)
-                .unwrap();
-
-        Ok(metadata)
+        generate_ec_attestation_key(sl, att_challenge, Digest::SHA_2_256, EcCurve::P_256)
     }
 }
 
@@ -834,7 +876,7 @@
     att_challenge: &[u8],
     digest: Digest,
     ec_curve: EcCurve,
-) -> binder::Result<KeyMetadata> {
+) -> binder::Result<Option<KeyMetadata>> {
     let alias = "ks_attest_ec_test_key";
     let gen_params = AuthSetBuilder::new()
         .no_auth_required()
@@ -844,7 +886,7 @@
         .digest(digest)
         .attestation_challenge(att_challenge.to_vec());
 
-    let attestation_key_metadata = sl.binder.generateKey(
+    let attestation_key_metadata = match sl.binder.generateKey(
         &KeyDescriptor {
             domain: Domain::APP,
             nspace: -1,
@@ -855,7 +897,23 @@
         &gen_params,
         0,
         b"entropy",
-    )?;
+    ) {
+        Ok(metadata) => metadata,
+        Err(e) => {
+            return if is_rkp_only_unknown_on_gsi(sl.level)
+                && e.service_specific_error() == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED.0
+            {
+                // GSI replaces the values for remote_prov_prop properties (since they’re
+                // system_internal_prop properties), so on GSI the properties are not
+                // reliable indicators of whether StrongBox/TEE are RKP-only or not.
+                // Test can be skipped if it generates a key with attestation but doesn't provide
+                // an ATTEST_KEY and rkp-only property is undetermined.
+                Ok(None)
+            } else {
+                Err(e)
+            };
+        }
+    };
 
     // Should have public certificate.
     assert!(attestation_key_metadata.certificate.is_some());
@@ -868,7 +926,7 @@
         &gen_params,
         KeyOrigin::GENERATED,
     );
-    Ok(attestation_key_metadata)
+    Ok(Some(attestation_key_metadata))
 }
 
 /// Generate EC-P-256 key and attest it with given attestation key.
@@ -1432,8 +1490,8 @@
     sl: &SecLevel,
     gen_params: &AuthSetBuilder,
     alias: &str,
-) -> binder::Result<KeyMetadata> {
-    let key_metadata = sl.binder.generateKey(
+) -> binder::Result<Option<KeyMetadata>> {
+    let key_metadata = match sl.binder.generateKey(
         &KeyDescriptor {
             domain: Domain::APP,
             nspace: -1,
@@ -1444,7 +1502,23 @@
         gen_params,
         0,
         b"entropy",
-    )?;
+    ) {
+        Ok(metadata) => metadata,
+        Err(e) => {
+            return if is_rkp_only_unknown_on_gsi(sl.level)
+                && e.service_specific_error() == ErrorCode::ATTESTATION_KEYS_NOT_PROVISIONED.0
+            {
+                // GSI replaces the values for remote_prov_prop properties (since they’re
+                // system_internal_prop properties), so on GSI the properties are not
+                // reliable indicators of whether StrongBox/TEE are RKP-only or not.
+                // Test can be skipped if it generates a key with attestation but doesn't provide
+                // an ATTEST_KEY and rkp-only property is undetermined.
+                Ok(None)
+            } else {
+                Err(e)
+            };
+        }
+    };
 
     if gen_params.iter().any(|kp| {
         matches!(
@@ -1489,7 +1563,7 @@
     }
     check_key_authorizations(sl, &key_metadata.authorizations, gen_params, KeyOrigin::GENERATED);
 
-    Ok(key_metadata)
+    Ok(Some(key_metadata))
 }
 
 /// Generate a key using given authorizations and create an operation using the generated key.
@@ -1498,8 +1572,10 @@
     gen_params: &AuthSetBuilder,
     op_params: &AuthSetBuilder,
     alias: &str,
-) -> binder::Result<CreateOperationResponse> {
-    let key_metadata = generate_key(sl, gen_params, alias)?;
+) -> binder::Result<Option<CreateOperationResponse>> {
+    let Some(key_metadata) = generate_key(sl, gen_params, alias)? else {
+        return Ok(None);
+    };
 
-    sl.binder.createOperation(&key_metadata.key, op_params, false)
+    sl.binder.createOperation(&key_metadata.key, op_params, false).map(Some)
 }