Retry getKeyAttestationApplicationId when fails

We want to retry the command getKeyAttestationApplicationId
some number of times before we return a failure to the user.
Getting the attest app id can fail at times, but if we retry
it may succeed.

Test: atest keystore2_test
Test: atest CtsKeystoreTestCases
Bug: 238619180
Change-Id: I77e76c2f33f08c9214ea290284e75078e3b1eea1
diff --git a/keystore/Android.bp b/keystore/Android.bp
index c79d00b..2d78f33 100644
--- a/keystore/Android.bp
+++ b/keystore/Android.bp
@@ -20,14 +20,14 @@
 
     sanitize: {
         misc_undefined: [
-             "signed-integer-overflow",
-             "unsigned-integer-overflow",
-             "shift",
-             "integer-divide-by-zero",
-             "implicit-unsigned-integer-truncation",
-             // BUG: 123630767
-             //"implicit-signed-integer-truncation",
-             "implicit-integer-sign-change",
+            "signed-integer-overflow",
+            "unsigned-integer-overflow",
+            "shift",
+            "integer-divide-by-zero",
+            "implicit-unsigned-integer-truncation",
+            // BUG: 123630767
+            //"implicit-signed-integer-truncation",
+            "implicit-integer-sign-change",
         ],
     },
 
@@ -66,7 +66,10 @@
 // in Tag::ATTESTATION_APPLICATION_ID
 cc_library {
     name: "libkeystore-attestation-application-id",
-    defaults: ["keystore_defaults"],
+    defaults: [
+        "keystore_defaults",
+        "keystore2_use_latest_aidl_ndk_shared",
+    ],
 
     srcs: [
         "keystore_attestation_id.cpp",
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 1534be1..d607fbf 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -29,6 +29,7 @@
 #include <binder/Parcelable.h>
 #include <binder/PersistableBundle.h>
 
+#include <aidl/android/system/keystore2/ResponseCode.h>
 #include <android/security/keystore/BpKeyAttestationApplicationIdProvider.h>
 #include <android/security/keystore/IKeyAttestationApplicationIdProvider.h>
 #include <android/security/keystore/KeyAttestationApplicationId.h>
@@ -49,6 +50,8 @@
 
 constexpr const char* kAttestationSystemPackageName = "AndroidSystem";
 constexpr const char* kUnknownPackageName = "UnknownPackage";
+constexpr const size_t kMaxAttempts = 3;
+constexpr const unsigned long kRetryIntervalUsecs = 500000;  // sleep for 500 ms
 
 std::vector<uint8_t> signature2SHA256(const security::keystore::Signature& sig) {
     std::vector<uint8_t> digest_buffer(SHA256_DIGEST_LENGTH);
@@ -56,6 +59,7 @@
     return digest_buffer;
 }
 
+using ::aidl::android::system::keystore2::ResponseCode;
 using ::android::security::keystore::BpKeyAttestationApplicationIdProvider;
 
 class KeyAttestationApplicationIdProvider : public BpKeyAttestationApplicationIdProvider {
@@ -279,17 +283,31 @@
     } else {
         /* Get the attestation application ID from package manager */
         auto& pm = KeyAttestationApplicationIdProvider::get();
-        auto status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+        ::android::binder::Status status;
+
+        // Retry on failure if a service specific error code.
+        for (size_t attempt{0}; attempt < kMaxAttempts; ++attempt) {
+            status = pm.getKeyAttestationApplicationId(uid, &key_attestation_id);
+            if (status.isOk()) {
+                break;
+            } else if (status.exceptionCode() != binder::Status::EX_SERVICE_SPECIFIC) {
+                ALOGW("Retry: key attestation ID failed with service specific error: %s %d",
+                      status.exceptionMessage().c_str(), status.serviceSpecificErrorCode());
+                usleep(kRetryIntervalUsecs);
+            } else {
+                ALOGW("Retry: key attestation ID failed with error: %s %d",
+                      status.exceptionMessage().c_str(), status.exceptionCode());
+                usleep(kRetryIntervalUsecs);
+            }
+        }
+
         // Package Manager call has failed, perform attestation but indicate that the
         // caller is unknown.
         if (!status.isOk()) {
             ALOGW("package manager request for key attestation ID failed with: %s %d",
                   status.exceptionMessage().c_str(), status.exceptionCode());
 
-            auto pinfo = KeyAttestationPackageInfo();
-            pinfo.packageName = String16(kUnknownPackageName);
-            pinfo.versionCode = 1;
-            key_attestation_id.packageInfos.push_back(std::move(pinfo));
+            return int32_t(ResponseCode::GET_ATTESTATION_APPLICATION_ID_FAILED);
         }
     }
 
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 951acb5..1661f8e 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -443,17 +443,19 @@
 
         // If there is an attestation challenge we need to get an application id.
         if params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) {
-            let aaid = {
-                let _wp = self
-                    .watch("In KeystoreSecurityLevel::add_required_parameters calling: get_aaid");
-                keystore2_aaid::get_aaid(uid)
-                    .map_err(|e| anyhow!(ks_err!("get_aaid returned status {}.", e)))
-            }?;
-
-            result.push(KeyParameter {
-                tag: Tag::ATTESTATION_APPLICATION_ID,
-                value: KeyParameterValue::Blob(aaid),
-            });
+            let _wp =
+                self.watch("In KeystoreSecurityLevel::add_required_parameters calling: get_aaid");
+            match keystore2_aaid::get_aaid(uid) {
+                Ok(aaid_ok) => {
+                    result.push(KeyParameter {
+                        tag: Tag::ATTESTATION_APPLICATION_ID,
+                        value: KeyParameterValue::Blob(aaid_ok),
+                    });
+                }
+                Err(e) => {
+                    return Err(anyhow!(e)).context(ks_err!("Attestation ID retrieval error."))
+                }
+            }
         }
 
         if params.iter().any(|kp| kp.tag == Tag::INCLUDE_UNIQUE_ID) {