summaryrefslogtreecommitdiff
path: root/identity
diff options
context:
space:
mode:
authorDavid Zeuthen <zeuthen@google.com>2022-11-14 15:22:24 -0500
committerDavid Zeuthen <zeuthen@google.com>2022-12-09 02:58:18 -0500
commitc239db4114246dbca23482bd4f2e3237fcb3524e (patch)
tree5ed03d409794fff486474f12f0d678148cc84fb6 /identity
parentfdf7f52a1d20e2c1f9bd03e363692f3562d1f287 (diff)
downloadsecurity-c239db4114246dbca23482bd4f2e3237fcb3524e.tar.gz
identity: Add support for setting minimum validity period for AuthKey.
This change adds support for specifying that an AuthKey should be replaced if it's going to expire within a certain amount of time configurable by the application. This also adds a way for the application to learn about the expiration time of currently configured AuthKeys. Combined these two changes allow an application to get a perfect picture of which AuthKeys are available, when they expire, and allows the application to refresh AuthKeys well ahead of expiration dates. Also remove checking storeStaticAuthenticationDataWithExpiration() is only available on HAL version 3 and later (feature version 202101 and later). This works on any HAL version. Bug: 241912421 Test: atest VtsHalIdentityTargetTest Test: atest android.security.identity.cts Change-Id: Ic8274088035c31f73ad61645ee5e0281b3460837
Diffstat (limited to 'identity')
-rw-r--r--identity/Credential.cpp37
-rw-r--r--identity/Credential.h4
-rw-r--r--identity/CredentialData.cpp24
-rw-r--r--identity/CredentialData.h8
-rw-r--r--identity/WritableCredential.cpp6
-rw-r--r--identity/WritableCredential.h4
-rw-r--r--identity/binder/android/security/identity/ICredential.aidl6
7 files changed, 67 insertions, 22 deletions
diff --git a/identity/Credential.cpp b/identity/Credential.cpp
index cbeb5084..0b1d171f 100644
--- a/identity/Credential.cpp
+++ b/identity/Credential.cpp
@@ -703,7 +703,8 @@ Status Credential::setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey)
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");
@@ -715,7 +716,7 @@ Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxU
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");
@@ -786,11 +787,6 @@ Status
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");
@@ -837,6 +833,29 @@ Status Credential::getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return
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) {
@@ -896,8 +915,8 @@ Status Credential::update(sp<IWritableCredential>* _aidl_return) {
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 0906fea2..4ecf92e0 100644
--- a/identity/Credential.h
+++ b/identity/Credential.h
@@ -78,7 +78,8 @@ class Credential : public BnCredential {
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 @@ class Credential : public BnCredential {
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 2189f909..fb083333 100644
--- a/identity/CredentialData.cpp
+++ b/identity/CredentialData.cpp
@@ -117,6 +117,7 @@ bool CredentialData::saveToDisk() const {
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 @@ bool CredentialData::loadFromDisk() {
authKeyDatas_.clear();
keyCount_ = 0;
maxUsesPerKey_ = 1;
+ minValidTimeMillis_ = 0;
optional<vector<uint8_t>> data = fileGetContents(fileName_);
if (!data) {
@@ -398,6 +400,14 @@ bool CredentialData::loadFromDisk() {
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 @@ optional<bool> CredentialData::credentialExists(const string& dataPath, uid_t ow
// ---
-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 @@ const vector<AuthKeyData>& CredentialData::getAuthKeyDatas() const {
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 @@ CredentialData::getAuthKeysNeedingCertification(const sp<IIdentityCredential>& h
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 e240e473..3f7cd3af 100644
--- a/identity/CredentialData.h
+++ b/identity/CredentialData.h
@@ -37,7 +37,6 @@ using ::android::hardware::identity::IIdentityCredential;
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 @@ class CredentialData : public RefBase {
bool deleteCredential();
- void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey);
+ void setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
+ int64_t minValidTimeMillis);
// Getters
@@ -107,7 +107,8 @@ class CredentialData : public RefBase {
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 @@ class CredentialData : public RefBase {
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 9827d754..d863494e 100644
--- a/identity/WritableCredential.cpp
+++ b/identity/WritableCredential.cpp
@@ -101,9 +101,11 @@ void WritableCredential::setAttestationCertificate(const vector<uint8_t>& attest
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 @@ WritableCredential::personalize(const vector<AccessControlProfileParcel>& access
}
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 838b9564..c92d58ab 100644
--- a/identity/WritableCredential.h
+++ b/identity/WritableCredential.h
@@ -45,7 +45,8 @@ class WritableCredential : public BnWritableCredential {
// 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 @@ class WritableCredential : public BnWritableCredential {
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/ICredential.aidl b/identity/binder/android/security/identity/ICredential.aidl
index e6a9fae0..875b9341 100644
--- a/identity/binder/android/security/identity/ICredential.aidl
+++ b/identity/binder/android/security/identity/ICredential.aidl
@@ -60,7 +60,9 @@ interface ICredential {
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 @@ interface ICredential {
int[] getAuthenticationDataUsageCount();
+ long[] getAuthenticationDataExpirations();
+
IWritableCredential update();
}