Add AuthorizationSetBuilder.

Actually move it from google_keymaster_test, where it was called
ParamBuilder.  This is a generally-useful tool.

Change-Id: I07200cdf2e5628289d9e544af02efe519ca124d3
diff --git a/authorization_set.cpp b/authorization_set.cpp
index 2586b40..e2bce14 100644
--- a/authorization_set.cpp
+++ b/authorization_set.cpp
@@ -36,6 +36,29 @@
     Reinitialize(set.elems_, set.elems_size_);
 }
 
+AuthorizationSet::AuthorizationSet(AuthorizationSetBuilder& builder) {
+    elems_ = builder.set.elems_;
+    builder.set.elems_ = NULL;
+
+    elems_size_ = builder.set.elems_size_;
+    builder.set.elems_size_ = 0;
+
+    elems_capacity_ = builder.set.elems_capacity_;
+    builder.set.elems_capacity_ = 0;
+
+    indirect_data_ = builder.set.indirect_data_;
+    builder.set.indirect_data_ = NULL;
+
+    indirect_data_capacity_ = builder.set.indirect_data_capacity_;
+    builder.set.indirect_data_capacity_ = 0;
+
+    indirect_data_size_ = builder.set.indirect_data_size_;
+    builder.set.indirect_data_size_ = 0;
+
+    error_ = builder.set.error_;
+    builder.set.error_ = OK;
+}
+
 AuthorizationSet::~AuthorizationSet() {
     FreeData();
 }
@@ -103,6 +126,33 @@
     error_ = error;
 }
 
+void AuthorizationSet::Deduplicate() {
+    qsort(elems_, elems_size_, sizeof(*elems_),
+          reinterpret_cast<int (*)(const void*, const void*)>(keymaster_param_compare));
+
+    size_t invalid_count = 0;
+    for (size_t i = 1; i < size(); ++i) {
+        if (elems_[i - 1].tag == KM_TAG_INVALID)
+            ++invalid_count;
+        else if (keymaster_param_compare(elems_ + i - 1, elems_ + i) == 0) {
+            // Mark dups as invalid.  Note that this "leaks" the data referenced by KM_BYTES and
+            // KM_BIGNUM entries, but those are just pointers into indirect_data_, so it will all
+            // get cleaned up.
+            elems_[i - 1].tag = KM_TAG_INVALID;
+            ++invalid_count;
+        }
+    }
+    if (size() > 0 && elems_[size() - 1].tag == KM_TAG_INVALID)
+        ++invalid_count;
+
+    if (invalid_count == 0)
+        return;
+
+    // Since KM_TAG_INVALID == 0, all of the invalid entries are first.
+    elems_size_ -= invalid_count;
+    memmove(elems_, elems_ + invalid_count, size() * sizeof(*elems_));
+}
+
 void AuthorizationSet::CopyToParamSet(keymaster_key_param_set_t* set) const {
     assert(set);