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();
}