Fix IC vts bugs and add tests for IC IWritableIdentityCredential.aidl interface.
Fixed following bugs in WritableIdentityCredential.cpp
- Do not allow startPersonalization to be called more than once per
aidl.
- Do not preceed with beginAddEntry if addAccessControlProfile and
startPersonalization profile count mismatch.
- Verify access control profile ids are unique.
- Do not let empty name space to mess up beginAddEntry.
- Do not allow beginAddEntry to add entries interleaving namespace
groupings. Enforce all entries must be added in namespace "groups"
per aidl.
- Fix counting error that allowed one entries to be added per name
space than startPersonalization limit.
- Do not approve finishAddingEntries if there are more profiles or
entries to be added than startPersonalization set accounting.
- Add testing utilities library for identity credential.
- Refactored end to end tests.
Bug: 154909726
Test: atest VtsHalIdentityTargetTest
Test: atest android.security.identity.cts
Merged-In: I51902681776c6230e49589fc75a8145e79d7d1a6
Change-Id: Ib7c108f67c61125edba6177dcac61cfbf58da671
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index 89f7f35..553a3d8 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -44,6 +44,8 @@
return false;
}
storageKey_ = random.value();
+ startPersonalizationCalled_ = false;
+ firstEntry_ = true;
return true;
}
@@ -105,6 +107,12 @@
ndk::ScopedAStatus WritableIdentityCredential::startPersonalization(
int32_t accessControlProfileCount, const vector<int32_t>& entryCounts) {
+ if (startPersonalizationCalled_) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_FAILED, "startPersonalization called already"));
+ }
+
+ startPersonalizationCalled_ = true;
numAccessControlProfileRemaining_ = accessControlProfileCount;
remainingEntryCounts_ = entryCounts;
entryNameSpace_ = "";
@@ -128,6 +136,13 @@
"numAccessControlProfileRemaining_ is 0 and expected non-zero"));
}
+ if (accessControlProfileIds_.find(id) != accessControlProfileIds_.end()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "Access Control Profile id must be unique"));
+ }
+ accessControlProfileIds_.insert(id);
+
// Spec requires if |userAuthenticationRequired| is false, then |timeoutMillis| must also
// be zero.
if (!userAuthenticationRequired && timeoutMillis != 0) {
@@ -184,12 +199,20 @@
}
// Handle initial beginEntry() call.
- if (entryNameSpace_ == "") {
+ if (firstEntry_) {
+ firstEntry_ = false;
entryNameSpace_ = nameSpace;
+ allNameSpaces_.insert(nameSpace);
}
// If the namespace changed...
if (nameSpace != entryNameSpace_) {
+ if (allNameSpaces_.find(nameSpace) != allNameSpaces_.end()) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "Name space cannot be added in interleaving fashion"));
+ }
+
// Then check that all entries in the previous namespace have been added..
if (remainingEntryCounts_[0] != 0) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -197,6 +220,8 @@
"New namespace but a non-zero number of entries remain to be added"));
}
remainingEntryCounts_.erase(remainingEntryCounts_.begin());
+ remainingEntryCounts_[0] -= 1;
+ allNameSpaces_.insert(nameSpace);
if (signedDataCurrentNamespace_.size() > 0) {
signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
@@ -330,6 +355,18 @@
ndk::ScopedAStatus WritableIdentityCredential::finishAddingEntries(
vector<int8_t>* outCredentialData, vector<int8_t>* outProofOfProvisioningSignature) {
+ if (numAccessControlProfileRemaining_ != 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "numAccessControlProfileRemaining_ is not 0 and expected zero"));
+ }
+
+ if (remainingEntryCounts_.size() > 1 || remainingEntryCounts_[0] != 0) {
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+ IIdentityCredentialStore::STATUS_INVALID_DATA,
+ "More entry spaces remain than startPersonalization configured"));
+ }
+
if (signedDataCurrentNamespace_.size() > 0) {
signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
}
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
index b182862..cb91f7b 100644
--- a/identity/aidl/default/WritableIdentityCredential.h
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -21,9 +21,11 @@
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
#include <cppbor.h>
+#include <set>
namespace aidl::android::hardware::identity {
+using ::std::set;
using ::std::string;
using ::std::vector;
@@ -66,6 +68,8 @@
// This is set in initialize().
vector<uint8_t> storageKey_;
+ bool startPersonalizationCalled_;
+ bool firstEntry_;
// These are set in getAttestationCertificate().
vector<uint8_t> credentialPrivKey_;
@@ -79,6 +83,9 @@
cppbor::Map signedDataNamespaces_;
cppbor::Array signedDataCurrentNamespace_;
+ // This field is initialized in addAccessControlProfile
+ set<int32_t> accessControlProfileIds_;
+
// These fields are initialized during beginAddEntry()
size_t entryRemainingBytes_;
vector<uint8_t> entryAdditionalData_;
@@ -86,6 +93,7 @@
string entryName_;
vector<int32_t> entryAccessControlProfileIds_;
vector<uint8_t> entryBytes_;
+ set<string> allNameSpaces_;
};
} // namespace aidl::android::hardware::identity