summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Pasanen <dan.pasanen@gmail.com>2017-04-05 07:27:52 -0500
committerDan Pasanen <dan.pasanen@gmail.com>2017-04-05 07:27:52 -0500
commitbfd6d4a94ed145482880c3f61bece014cab39b8d (patch)
tree9e208ad89a6b94154f28e09769d937b549e1772d
parent5c733cf77a1ee79bcfa35ecb1e0ffd709033f2ca (diff)
parent391a367df2352bed7e70885493421892a1cdaffc (diff)
downloadandroid_system_keymaster-staging/cm-14.1_android-7.1.2_r2.tar.gz
android_system_keymaster-staging/cm-14.1_android-7.1.2_r2.tar.bz2
android_system_keymaster-staging/cm-14.1_android-7.1.2_r2.zip
Merge tag 'android-7.1.2_r2' into cm-14.1staging/cm-14.1_android-7.1.2_r2
Android 7.1.2 Release 2 (N2G47E) # gpg: Signature made Mon 03 Apr 2017 01:41:52 AM CDT # gpg: using DSA key E8AD3F819AB10E78 # gpg: Can't check signature: No public key
-rw-r--r--authorization_set.cpp26
-rw-r--r--authorization_set_test.cpp115
-rw-r--r--include/keymaster/authorization_set.h11
3 files changed, 152 insertions, 0 deletions
diff --git a/authorization_set.cpp b/authorization_set.cpp
index 9f6810d..4cf070c 100644
--- a/authorization_set.cpp
+++ b/authorization_set.cpp
@@ -179,6 +179,32 @@ void AuthorizationSet::Deduplicate() {
memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
}
+void AuthorizationSet::Union(const keymaster_key_param_set_t& set) {
+ if (set.length == 0)
+ return;
+
+ push_back(set);
+ Deduplicate();
+}
+
+void AuthorizationSet::Difference(const keymaster_key_param_set_t& set) {
+ if (set.length == 0)
+ return;
+
+ Deduplicate();
+
+ for (size_t i = 0; i < set.length; i++) {
+ int index = -1;
+ do {
+ index = find(set.params[i].tag, index);
+ if (index != -1 && keymaster_param_compare(&elems_[index], &set.params[i]) == 0) {
+ erase(index);
+ break;
+ }
+ } while (index != -1);
+ }
+}
+
void AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
assert(set);
diff --git a/authorization_set_test.cpp b/authorization_set_test.cpp
index ddc7df3..f3f4412 100644
--- a/authorization_set_test.cpp
+++ b/authorization_set_test.cpp
@@ -626,5 +626,120 @@ TEST(Deduplication, DuplicateBlob) {
// The real test here is that valgrind reports no leak.
}
+TEST(Union, Disjoint) {
+ AuthorizationSet set1(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet set2(AuthorizationSetBuilder()
+ .Authorization(TAG_USER_ID, 7)
+ .Authorization(TAG_APPLICATION_DATA, "foo", 3)
+ .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
+
+ AuthorizationSet expected(AuthorizationSetBuilder()
+ .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD)
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_USER_ID, 7)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4)
+ .Authorization(TAG_APPLICATION_DATA, "foo", 3));
+
+ set1.Union(set2);
+ EXPECT_EQ(expected, set1);
+}
+
+TEST(Union, Overlap) {
+ AuthorizationSet set1(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet set2(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet expected(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ set1.Union(set2);
+ EXPECT_EQ(expected, set1);
+}
+
+TEST(Union, Empty) {
+ AuthorizationSet set1(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet set2;
+
+ AuthorizationSet expected(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ set1.Union(set2);
+ EXPECT_EQ(expected, set1);
+}
+
+TEST(Difference, Disjoint) {
+ AuthorizationSet set1(AuthorizationSetBuilder()
+ .Authorization(TAG_APPLICATION_DATA, "data", 4)
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10));
+
+ AuthorizationSet set2(AuthorizationSetBuilder()
+ .Authorization(TAG_USER_ID, 7)
+ .Authorization(TAG_APPLICATION_DATA, "foo", 3)
+ .Authorization(TAG_USER_AUTH_TYPE, HW_AUTH_PASSWORD));
+
+ // Elements are the same as set1, but happen to be in a different order
+ AuthorizationSet expected(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ set1.Difference(set2);
+ EXPECT_EQ(expected, set1);
+}
+
+TEST(Difference, Overlap) {
+ AuthorizationSet set1(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet set2(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet empty;
+ set1.Difference(set2);
+ EXPECT_EQ(empty, set1);
+ EXPECT_EQ(0U, set1.size());
+}
+
+TEST(Difference, NullSet) {
+ AuthorizationSet set1(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ AuthorizationSet set2;
+
+ AuthorizationSet expected(AuthorizationSetBuilder()
+ .Authorization(TAG_PURPOSE, KM_PURPOSE_VERIFY)
+ .Authorization(TAG_ACTIVE_DATETIME, 10)
+ .Authorization(TAG_APPLICATION_DATA, "data", 4));
+
+ set1.Difference(set2);
+ EXPECT_EQ(expected, set1);
+}
+
} // namespace test
} // namespace keymaster
diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h
index ec68de0..1a7894d 100644
--- a/include/keymaster/authorization_set.h
+++ b/include/keymaster/authorization_set.h
@@ -164,6 +164,17 @@ class AuthorizationSet : public Serializable, public keymaster_key_param_set_t {
void Deduplicate();
/**
+ * Adds all elements from \p set that are not already present in this AuthorizationSet. As a
+ * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
+ */
+ void Union(const keymaster_key_param_set_t& set);
+
+ /**
+ * Removes all elements in \p set from this AuthorizationSet.
+ */
+ void Difference(const keymaster_key_param_set_t& set);
+
+ /**
* Returns the data in a keymaster_key_param_set_t, suitable for returning to C code. For C
* compatibility, the contents are malloced, not new'ed, and so must be freed with free(), or
* better yet with keymaster_free_param_set, not delete. The caller takes ownership.