Merge changes from topic "ic-android14"

* changes:
  identity: Add support for setting minimum validity period for AuthKey.
  identity: Add support for ECDSA auth and don't require session encryption.
diff --git a/identity/Credential.cpp b/identity/Credential.cpp
index c67fe4a..0b1d171 100644
--- a/identity/Credential.cpp
+++ b/identity/Credential.cpp
@@ -554,9 +554,18 @@
         ret.resultNamespaces.push_back(resultNamespaceParcel);
     }
 
-    status = halBinder->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
-    if (!status.isOk()) {
-        return halStatusToGenericError(status);
+    // API version 5 (feature version 202301) supports both MAC and ECDSA signature.
+    if (halApiVersion_ >= 5) {
+        status = halBinder->finishRetrievalWithSignature(&ret.mac, &ret.deviceNameSpaces,
+                                                         &ret.signature);
+        if (!status.isOk()) {
+            return halStatusToGenericError(status);
+        }
+    } else {
+        status = halBinder->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
+        if (!status.isOk()) {
+            return halStatusToGenericError(status);
+        }
     }
     ret.staticAuthenticationData = selectedAuthKeyStaticAuthData_;
 
@@ -694,7 +703,8 @@
     return Status::ok();
 }
 
-Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey) {
+Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey,
+                                                  int64_t minValidTimeMillis) {
     if (halSessionBinder_) {
         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                 "Cannot be used with session");
@@ -706,7 +716,7 @@
         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                 "Error loading data for credential");
     }
-    data->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey);
+    data->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey, minValidTimeMillis);
     if (!data->saveToDisk()) {
         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                 "Error saving data");
@@ -777,11 +787,6 @@
 Credential::storeStaticAuthenticationDataWithExpiration(const AuthKeyParcel& authenticationKey,
                                                         int64_t expirationDateMillisSinceEpoch,
                                                         const vector<uint8_t>& staticAuthData) {
-    if (halApiVersion_ < 3) {
-        return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
-                                                "Not implemented by HAL");
-    }
-
     if (halSessionBinder_) {
         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
                                                 "Cannot be used with session");
@@ -828,6 +833,29 @@
     return Status::ok();
 }
 
+Status Credential::getAuthenticationDataExpirations(vector<int64_t>* _aidl_return) {
+    if (halSessionBinder_) {
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Cannot be used with session");
+    }
+
+    sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
+    if (!data->loadFromDisk()) {
+        LOG(ERROR) << "Error loading data for credential";
+        return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
+                                                "Error loading data for credential");
+    }
+    const vector<AuthKeyData>& authKeyDatas = data->getAuthKeyDatas();
+    vector<int64_t> ret;
+    ret.reserve(authKeyDatas.size());
+    for (const AuthKeyData& authKeyData : authKeyDatas) {
+        // Note: value is INT64_MAX if expiration date is not set.
+        ret.push_back(authKeyData.expirationDateMillisSinceEpoch);
+    }
+    *_aidl_return = ret;
+    return Status::ok();
+}
+
 optional<string> extractDocType(const vector<uint8_t>& credentialData) {
     auto [item, _ /* newPos */, message] = cppbor::parse(credentialData);
     if (item == nullptr) {
@@ -887,8 +915,8 @@
         dataPath_, credentialName_, docType.value(), true, hwInfo_, halWritableCredential);
 
     writableCredential->setAttestationCertificate(data->getAttestationCertificate());
-    auto [keyCount, maxUsesPerKey] = data->getAvailableAuthenticationKeys();
-    writableCredential->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey);
+    auto [keyCount, maxUsesPerKey, minValidTimeMillis] = data->getAvailableAuthenticationKeys();
+    writableCredential->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey, minValidTimeMillis);
 
     // Because its data has changed, we need to replace the binder for the
     // IIdentityCredential when the credential has been updated... otherwise the
diff --git a/identity/Credential.h b/identity/Credential.h
index 0906fea..4ecf92e 100644
--- a/identity/Credential.h
+++ b/identity/Credential.h
@@ -78,7 +78,8 @@
                       bool allowUsingExpiredKeys, bool incrementUsageCount,
                       GetEntriesResultParcel* _aidl_return) override;
 
-    Status setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey) override;
+    Status setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey,
+                                          int64_t minValidTimeMillis) override;
     Status getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) override;
     Status storeStaticAuthenticationData(const AuthKeyParcel& authenticationKey,
                                          const vector<uint8_t>& staticAuthData) override;
@@ -87,6 +88,7 @@
                                                 int64_t expirationDateMillisSinceEpoch,
                                                 const vector<uint8_t>& staticAuthData) override;
     Status getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return) override;
+    Status getAuthenticationDataExpirations(vector<int64_t>* _aidl_return) override;
 
     Status update(sp<IWritableCredential>* _aidl_return) override;
 
diff --git a/identity/CredentialData.cpp b/identity/CredentialData.cpp
index 2189f90..fb08333 100644
--- a/identity/CredentialData.cpp
+++ b/identity/CredentialData.cpp
@@ -117,6 +117,7 @@
     map.add("entryData", std::move(encryptedBlobsMap));
     map.add("authKeyCount", keyCount_);
     map.add("maxUsesPerAuthKey", maxUsesPerKey_);
+    map.add("minValidTimeMillis", minValidTimeMillis_);
 
     cppbor::Array authKeyDatasArray;
     for (const AuthKeyData& data : authKeyDatas_) {
@@ -253,6 +254,7 @@
     authKeyDatas_.clear();
     keyCount_ = 0;
     maxUsesPerKey_ = 1;
+    minValidTimeMillis_ = 0;
 
     optional<vector<uint8_t>> data = fileGetContents(fileName_);
     if (!data) {
@@ -398,6 +400,14 @@
                 return false;
             }
             maxUsesPerKey_ = number->value();
+
+        } else if (key == "minValidTimeMillis") {
+            const cppbor::Int* number = valueItem->asInt();
+            if (number == nullptr) {
+                LOG(ERROR) << "Value for minValidTimeMillis is not a number";
+                return false;
+            }
+            minValidTimeMillis_ = number->value();
         }
     }
 
@@ -479,9 +489,11 @@
 
 // ---
 
-void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey) {
+void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
+                                                    int64_t minValidTimeMillis) {
     keyCount_ = keyCount;
     maxUsesPerKey_ = maxUsesPerKey;
+    minValidTimeMillis_ = minValidTimeMillis;
 
     // If growing the number of auth keys (prevKeyCount < keyCount_ case) we'll add
     // new AuthKeyData structs to |authKeyDatas_| and each struct will have empty |certificate|
@@ -499,8 +511,9 @@
     return authKeyDatas_;
 }
 
-pair<int /* keyCount */, int /*maxUsersPerKey */> CredentialData::getAvailableAuthenticationKeys() {
-    return std::make_pair(keyCount_, maxUsesPerKey_);
+tuple<int /* keyCount */, int /*maxUsersPerKey */, int64_t /* minValidTimeMillis */>
+CredentialData::getAvailableAuthenticationKeys() const {
+    return std::make_tuple(keyCount_, maxUsesPerKey_, minValidTimeMillis_);
 }
 
 AuthKeyData* CredentialData::findAuthKey_(bool allowUsingExhaustedKeys,
@@ -573,9 +586,10 @@
 
     for (AuthKeyData& data : authKeyDatas_) {
         bool keyExceedUseCount = (data.useCount >= maxUsesPerKey_);
-        bool keyBeyondExpirationDate = (nowMilliSeconds > data.expirationDateMillisSinceEpoch);
+        int64_t expirationDateAdjusted = data.expirationDateMillisSinceEpoch - minValidTimeMillis_;
+        bool keyBeyondAdjustedExpirationDate = (nowMilliSeconds > expirationDateAdjusted);
         bool newKeyNeeded =
-            (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondExpirationDate;
+            (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondAdjustedExpirationDate;
         bool certificationPending = (data.pendingCertificate.size() > 0);
         if (newKeyNeeded && !certificationPending) {
             vector<uint8_t> signingKeyBlob;
diff --git a/identity/CredentialData.h b/identity/CredentialData.h
index e240e47..3f7cd3a 100644
--- a/identity/CredentialData.h
+++ b/identity/CredentialData.h
@@ -37,7 +37,6 @@
 using ::android::hardware::identity::SecureAccessControlProfile;
 using ::std::map;
 using ::std::optional;
-using ::std::pair;
 using ::std::string;
 using ::std::tuple;
 using ::std::vector;
@@ -89,7 +88,8 @@
 
     bool deleteCredential();
 
-    void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey);
+    void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
+                                        int64_t minValidTimeMillis);
 
     // Getters
 
@@ -107,7 +107,8 @@
 
     const vector<AuthKeyData>& getAuthKeyDatas() const;
 
-    pair<int /* keyCount */, int /*maxUsersPerKey */> getAvailableAuthenticationKeys();
+    tuple<int /* keyCount */, int /*maxUsersPerKey */, int64_t /* minValidTimeMillis */>
+    getAvailableAuthenticationKeys() const;
 
     // Returns |nullptr| if a suitable key cannot be found. Otherwise returns
     // the authentication and increases its use-count.
@@ -143,6 +144,7 @@
 
     int keyCount_ = 0;
     int maxUsesPerKey_ = 1;
+    int64_t minValidTimeMillis_ = 0;
     vector<AuthKeyData> authKeyDatas_;  // Always |keyCount_| long.
 };
 
diff --git a/identity/WritableCredential.cpp b/identity/WritableCredential.cpp
index 9827d75..d863494 100644
--- a/identity/WritableCredential.cpp
+++ b/identity/WritableCredential.cpp
@@ -101,9 +101,11 @@
     attestationCertificate_ = attestationCertificate;
 }
 
-void WritableCredential::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey) {
+void WritableCredential::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
+                                                        int64_t minValidTimeMillis) {
     keyCount_ = keyCount;
     maxUsesPerKey_ = maxUsesPerKey;
+    minValidTimeMillis_ = minValidTimeMillis;
 }
 
 ssize_t WritableCredential::calcExpectedProofOfProvisioningSize(
@@ -260,7 +262,7 @@
     }
     data.setCredentialData(credentialData);
 
-    data.setAvailableAuthenticationKeys(keyCount_, maxUsesPerKey_);
+    data.setAvailableAuthenticationKeys(keyCount_, maxUsesPerKey_, minValidTimeMillis_);
 
     if (!data.saveToDisk()) {
         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
diff --git a/identity/WritableCredential.h b/identity/WritableCredential.h
index 838b956..c92d58a 100644
--- a/identity/WritableCredential.h
+++ b/identity/WritableCredential.h
@@ -45,7 +45,8 @@
 
     // Used when updating a credential
     void setAttestationCertificate(const vector<uint8_t>& attestationCertificate);
-    void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey);
+    void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
+                                        int64_t minValidTimeMillis);
 
     // Used by Credential::update()
     void setCredentialToReloadWhenUpdated(sp<Credential> credential);
@@ -69,6 +70,7 @@
     vector<uint8_t> attestationCertificate_;
     int keyCount_ = 0;
     int maxUsesPerKey_ = 1;
+    int64_t minValidTimeMillis_ = 0;
 
     sp<Credential> credentialToReloadWhenUpdated_;
 
diff --git a/identity/binder/android/security/identity/GetEntriesResultParcel.aidl b/identity/binder/android/security/identity/GetEntriesResultParcel.aidl
index 03b363c..51281b9 100644
--- a/identity/binder/android/security/identity/GetEntriesResultParcel.aidl
+++ b/identity/binder/android/security/identity/GetEntriesResultParcel.aidl
@@ -26,4 +26,5 @@
     byte[] deviceNameSpaces;
     byte[] mac;
     byte[] staticAuthenticationData;
+    byte[] signature;                      // Added in Android 14 / U
 }
diff --git a/identity/binder/android/security/identity/ICredential.aidl b/identity/binder/android/security/identity/ICredential.aidl
index e6a9fae..875b934 100644
--- a/identity/binder/android/security/identity/ICredential.aidl
+++ b/identity/binder/android/security/identity/ICredential.aidl
@@ -60,7 +60,9 @@
                                       in boolean allowUsingExpiredKeys,
                                       in boolean incrementUsageCount);
 
-    void setAvailableAuthenticationKeys(in int keyCount, in int maxUsesPerKey);
+    void setAvailableAuthenticationKeys(in int keyCount,
+                                        in int maxUsesPerKey,
+                                        in long minValidTimeMillis);
 
     AuthKeyParcel[] getAuthKeysNeedingCertification();
 
@@ -73,6 +75,8 @@
 
     int[] getAuthenticationDataUsageCount();
 
+    long[] getAuthenticationDataExpirations();
+
     IWritableCredential update();
 }