Merge "Add new auth types to capture bitmask values and unspecified auth types." into main
diff --git a/keystore2/src/crypto/lib.rs b/keystore2/src/crypto/lib.rs
index 09b84ec..b6f308b 100644
--- a/keystore2/src/crypto/lib.rs
+++ b/keystore2/src/crypto/lib.rs
@@ -317,7 +317,7 @@
     }
 }
 
-impl<'a> BorrowedECPoint<'a> {
+impl BorrowedECPoint<'_> {
     /// Get the wrapped EC_POINT object.
     pub fn get_point(&self) -> &EC_POINT {
         // Safety: We only create BorrowedECPoint objects for valid EC_POINTs.
diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs
index 42fd764..3e65753 100644
--- a/keystore2/src/super_key.rs
+++ b/keystore2/src/super_key.rs
@@ -1218,7 +1218,7 @@
     Ref(&'a [u8]),
 }
 
-impl<'a> KeyBlob<'a> {
+impl KeyBlob<'_> {
     pub fn force_reencrypt(&self) -> bool {
         if let KeyBlob::Sensitive { force_reencrypt, .. } = self {
             *force_reencrypt
@@ -1229,7 +1229,7 @@
 }
 
 /// Deref returns a reference to the key material in any variant.
-impl<'a> Deref for KeyBlob<'a> {
+impl Deref for KeyBlob<'_> {
     type Target = [u8];
 
     fn deref(&self) -> &Self::Target {
diff --git a/keystore2/test_utils/attestation/lib.rs b/keystore2/test_utils/attestation/lib.rs
index 8ae4fc0..31d3314 100644
--- a/keystore2/test_utils/attestation/lib.rs
+++ b/keystore2/test_utils/attestation/lib.rs
@@ -63,7 +63,7 @@
     pub hw_enforced: AuthorizationList<'a>,
 }
 
-impl<'a> AssociatedOid for AttestationExtension<'a> {
+impl AssociatedOid for AttestationExtension<'_> {
     const OID: ObjectIdentifier = ATTESTATION_EXTENSION_OID;
 }
 
@@ -112,7 +112,7 @@
     pub version: i64,
 }
 
-impl<'a> DerOrd for PackageInfoRecord<'a> {
+impl DerOrd for PackageInfoRecord<'_> {
     fn der_cmp(&self, other: &Self) -> Result<std::cmp::Ordering, der::Error> {
         self.package_name.der_cmp(&other.package_name)
     }
@@ -139,7 +139,7 @@
     pub auths: Cow<'a, [KeyParameter]>,
 }
 
-impl<'a> From<Vec<KeyParameter>> for AuthorizationList<'a> {
+impl From<Vec<KeyParameter>> for AuthorizationList<'_> {
     /// Build an `AuthorizationList` using a set of key parameters.
     fn from(auths: Vec<KeyParameter>) -> Self {
         AuthorizationList { auths: auths.into() }
@@ -149,7 +149,7 @@
 impl<'a> Sequence<'a> for AuthorizationList<'a> {}
 
 /// Stub (non-)implementation of DER-encoding, needed to implement [`Sequence`].
-impl<'a> EncodeValue for AuthorizationList<'a> {
+impl EncodeValue for AuthorizationList<'_> {
     fn value_len(&self) -> der::Result<Length> {
         unimplemented!("Only decoding is implemented");
     }
diff --git a/keystore2/tests/keystore2_client_authorizations_tests.rs b/keystore2/tests/keystore2_client_authorizations_tests.rs
index 6fa3d64..a546799 100644
--- a/keystore2/tests/keystore2_client_authorizations_tests.rs
+++ b/keystore2/tests/keystore2_client_authorizations_tests.rs
@@ -522,6 +522,10 @@
 #[test]
 fn keystore2_gen_key_auth_usage_count_limit() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() {
+        // `USAGE_COUNT_LIMIT` is supported from KeyMint1.0
+        return;
+    }
     const MAX_USES_COUNT: i32 = 3;
 
     let gen_params = authorizations::AuthSetBuilder::new()
@@ -546,6 +550,10 @@
 #[test]
 fn keystore2_gen_key_auth_usage_count_limit_one() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() {
+        // `USAGE_COUNT_LIMIT` is supported from KeyMint1.0
+        return;
+    }
     const MAX_USES_COUNT: i32 = 1;
 
     let gen_params = authorizations::AuthSetBuilder::new()
@@ -569,6 +577,10 @@
 #[test]
 fn keystore2_gen_non_attested_key_auth_usage_count_limit() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() {
+        // `USAGE_COUNT_LIMIT` is supported from KeyMint1.0
+        return;
+    }
     const MAX_USES_COUNT: i32 = 2;
 
     let gen_params = authorizations::AuthSetBuilder::new()
@@ -631,6 +643,12 @@
 #[test]
 fn keystore2_gen_key_auth_include_unique_id_success() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() {
+        // b/387208956 - Some older devices with Keymaster implementations fail to generate an
+        // attestation key with `INCLUDE_UNIQUE_ID`, but this was not previously tested. Skip this
+        // test on devices with Keymaster implementation.
+        return;
+    }
 
     let alias_first = "ks_test_auth_tags_test_1";
     if let Some(unique_id_first) = gen_key_including_unique_id(&sl, alias_first) {
@@ -1007,6 +1025,11 @@
         // Module info is only populated if the flag is set.
         return;
     }
+
+    // Test should not run before MODULE_HASH supplementary info is populated.
+    assert!(rustutils::system_properties::read_bool("keystore.module_hash.sent", false)
+        .unwrap_or(false));
+
     let sl = SecLevel::tee();
 
     // Retrieve the input value that gets hashed into the attestation.
@@ -1025,6 +1048,11 @@
     assert!(result.is_err());
     assert_eq!(result.unwrap_err(), Error::Rc(ResponseCode::INVALID_ARGUMENT));
 
+    if sl.get_keymint_version() < 400 {
+        // Module hash will only be populated in KeyMint if the underlying device is KeyMint V4+.
+        return;
+    }
+
     // Generate an attestation.
     let alias = "ks_module_info_test";
     let params = authorizations::AuthSetBuilder::new()
diff --git a/keystore2/tests/keystore2_client_test_utils.rs b/keystore2/tests/keystore2_client_test_utils.rs
index aa084ca..b9a8243 100644
--- a/keystore2/tests/keystore2_client_test_utils.rs
+++ b/keystore2/tests/keystore2_client_test_utils.rs
@@ -519,9 +519,7 @@
 // then returns an empty byte vector.
 pub fn get_system_prop(name: &str) -> Vec<u8> {
     match rustutils::system_properties::read(name) {
-        Ok(Some(value)) => {
-            return value.as_bytes().to_vec();
-        }
+        Ok(Some(value)) => value.as_bytes().to_vec(),
         _ => {
             vec![]
         }
diff --git a/keystore2/watchdog/Android.bp b/keystore2/watchdog/Android.bp
index 5074388..9a99f10 100644
--- a/keystore2/watchdog/Android.bp
+++ b/keystore2/watchdog/Android.bp
@@ -26,6 +26,7 @@
     crate_name: "watchdog_rs",
     srcs: ["src/lib.rs"],
     rustlibs: [
+        "libchrono",
         "liblog_rust",
     ],
 }
diff --git a/keystore2/watchdog/src/lib.rs b/keystore2/watchdog/src/lib.rs
index b4a1e0f..f6a1291 100644
--- a/keystore2/watchdog/src/lib.rs
+++ b/keystore2/watchdog/src/lib.rs
@@ -64,6 +64,18 @@
     context: Option<Box<dyn std::fmt::Debug + Send + 'static>>,
 }
 
+impl Record {
+    // Return a string representation of the start time of the record.
+    //
+    // Times are hard. This may not be accurate (e.g. if the system clock has been modified since
+    // the watchdog started), but it's _really_ useful to get a starting wall time for overrunning
+    // watchdogs.
+    fn started_utc(&self) -> String {
+        let started_utc = chrono::Utc::now() - self.started.elapsed();
+        format!("{}", started_utc.format("%m-%d %H:%M:%S%.3f UTC"))
+    }
+}
+
 struct WatchdogState {
     state: State,
     thread: Option<thread::JoinHandle<()>>,
@@ -137,8 +149,13 @@
             .filter(|(_, r)| r.deadline.saturating_duration_since(now) == Duration::new(0, 0))
             .collect();
 
-        log::warn!("When extracting from a bug report, please include this header");
-        log::warn!("and all {} records below.", overdue_records.len());
+        log::warn!(
+            concat!(
+                "When extracting from a bug report, please include this header ",
+                "and all {} records below (to footer)"
+            ),
+            overdue_records.len()
+        );
 
         // Watch points can be nested, i.e., a single thread may have multiple armed
         // watch points. And the most recent on each thread (thread recent) is closest to the point
@@ -169,9 +186,10 @@
                 match &r.context {
                     Some(ctx) => {
                         log::warn!(
-                            "{:?} {} Pending: {:?} Overdue {:?} for {:?}",
+                            "{:?} {} Started: {} Pending: {:?} Overdue {:?} for {:?}",
                             i.tid,
                             i.id,
+                            r.started_utc(),
                             r.started.elapsed(),
                             r.deadline.elapsed(),
                             ctx
@@ -179,9 +197,10 @@
                     }
                     None => {
                         log::warn!(
-                            "{:?} {} Pending: {:?} Overdue {:?}",
+                            "{:?} {} Started: {} Pending: {:?} Overdue {:?}",
                             i.tid,
                             i.id,
+                            r.started_utc(),
                             r.started.elapsed(),
                             r.deadline.elapsed()
                         );
@@ -200,17 +219,19 @@
             if timeout_left == Duration::new(0, 0) {
                 match &record.context {
                     Some(ctx) => log::info!(
-                        "Watchdog complete for: {:?} {} Pending: {:?} Overdue {:?} for {:?}",
+                        "Watchdog complete for: {:?} {} Started: {} Pending: {:?} Overdue {:?} for {:?}",
                         index.tid,
                         index.id,
+                        record.started_utc(),
                         record.started.elapsed(),
                         record.deadline.elapsed(),
                         ctx
                     ),
                     None => log::info!(
-                        "Watchdog complete for: {:?} {} Pending: {:?} Overdue {:?}",
+                        "Watchdog complete for: {:?} {} Started: {} Pending: {:?} Overdue {:?}",
                         index.tid,
                         index.id,
+                        record.started_utc(),
                         record.started.elapsed(),
                         record.deadline.elapsed()
                     ),