summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/attrs.c52
-rw-r--r--common/attrs.h4
-rw-r--r--common/tests/test-attrs.c103
3 files changed, 153 insertions, 6 deletions
diff --git a/common/attrs.c b/common/attrs.c
index 759bb75..0ccf832 100644
--- a/common/attrs.c
+++ b/common/attrs.c
@@ -84,7 +84,8 @@ p11_attrs_free (void *attrs)
static CK_ATTRIBUTE *
attrs_build (CK_ATTRIBUTE *attrs,
CK_ULONG count_to_add,
- bool copy,
+ bool take_values,
+ bool override,
CK_ATTRIBUTE * (*generator) (void *),
void *state)
{
@@ -116,18 +117,28 @@ attrs_build (CK_ATTRIBUTE *attrs,
for (j = 0; attr == NULL && j < current; j++) {
if (attrs[j].type == add->type) {
attr = attrs + j;
- free (attrs[j].pValue);
break;
}
}
+ /* The attribute doesn't exist */
if (attr == NULL) {
attr = attrs + at;
at++;
+
+ /* The attribute exists and we're not overriding */
+ } else if (!override) {
+ if (take_values)
+ free (add->pValue);
+ continue;
+
+ /* The attribute exitss, and we're overriding */
+ } else {
+ free (attr->pValue);
}
memcpy (attr, add, sizeof (CK_ATTRIBUTE));
- if (copy)
+ if (!take_values)
attr->pValue = memdup (attr->pValue, attr->ulValueLen);
}
@@ -158,7 +169,8 @@ p11_attrs_build (CK_ATTRIBUTE *attrs,
va_end (va);
va_start (va, attrs);
- attrs = attrs_build (attrs, count, true, vararg_generator, &va);
+ attrs = attrs_build (attrs, count, false, true,
+ vararg_generator, &va);
va_end (va);
return attrs;
@@ -176,7 +188,8 @@ p11_attrs_buildn (CK_ATTRIBUTE *attrs,
const CK_ATTRIBUTE *add,
CK_ULONG count)
{
- return attrs_build (attrs, count, true, template_generator, &add);
+ return attrs_build (attrs, count, false, true,
+ template_generator, &add);
}
CK_ATTRIBUTE *
@@ -187,7 +200,34 @@ p11_attrs_take (CK_ATTRIBUTE *attrs,
{
CK_ATTRIBUTE attr = { type, value, length };
CK_ATTRIBUTE *add = &attr;
- return attrs_build (attrs, 1, false, template_generator, &add);
+ return attrs_build (attrs, 1, true, true,
+ template_generator, &add);
+}
+
+CK_ATTRIBUTE *
+p11_attrs_merge (CK_ATTRIBUTE *attrs,
+ CK_ATTRIBUTE *merge,
+ bool replace)
+{
+ CK_ATTRIBUTE *ptr;
+ CK_ULONG count;
+
+ if (attrs == NULL)
+ return merge;
+
+ ptr = merge;
+ count = p11_attrs_count (merge);
+
+ attrs = attrs_build (attrs, count, true, replace,
+ template_generator, &ptr);
+
+ /*
+ * Since we're supposed to own the merge attributes,
+ * free the container array.
+ */
+ free (merge);
+
+ return attrs;
}
CK_ATTRIBUTE *
diff --git a/common/attrs.h b/common/attrs.h
index 870f0d1..4e3f46c 100644
--- a/common/attrs.h
+++ b/common/attrs.h
@@ -55,6 +55,10 @@ CK_ATTRIBUTE * p11_attrs_take (CK_ATTRIBUTE *attrs,
CK_VOID_PTR value,
CK_ULONG length);
+CK_ATTRIBUTE * p11_attrs_merge (CK_ATTRIBUTE *attrs,
+ CK_ATTRIBUTE *merge,
+ bool replace);
+
bool p11_attrs_is_empty (const CK_ATTRIBUTE *attrs);
CK_ULONG p11_attrs_count (const CK_ATTRIBUTE *attrs);
diff --git a/common/tests/test-attrs.c b/common/tests/test-attrs.c
index 09d0ace..49350be 100644
--- a/common/tests/test-attrs.c
+++ b/common/tests/test-attrs.c
@@ -290,6 +290,106 @@ test_take (CuTest *tc)
p11_attrs_free (attrs);
}
+
+static void
+test_merge_replace (CuTest *tc)
+{
+ CK_ATTRIBUTE initial[] = {
+ { CKA_LABEL, "label", 5 },
+ { CKA_VALUE, "nine", 4 },
+ };
+
+ CK_ATTRIBUTE extra[] = {
+ { CKA_LABEL, "boooyah", 7 },
+ { CKA_APPLICATION, "disco", 5 },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *merge;
+
+ attrs = p11_attrs_buildn (NULL, initial, 2);
+ merge = p11_attrs_buildn (NULL, extra, 2);
+ attrs = p11_attrs_merge (attrs, merge, true);
+ CuAssertPtrNotNull (tc, attrs);
+
+ CuAssertTrue (tc, attrs[0].type == CKA_LABEL);
+ CuAssertIntEquals (tc, 7, attrs[0].ulValueLen);
+ CuAssertTrue (tc, memcmp (attrs[0].pValue, "boooyah", 7) == 0);
+
+ CuAssertPtrNotNull (tc, attrs);
+ CuAssertTrue (tc, attrs[1].type == CKA_VALUE);
+ CuAssertIntEquals (tc, 4, attrs[1].ulValueLen);
+ CuAssertTrue (tc, memcmp (attrs[1].pValue, "nine", 4) == 0);
+
+ CuAssertPtrNotNull (tc, attrs);
+ CuAssertTrue (tc, attrs[2].type == CKA_APPLICATION);
+ CuAssertIntEquals (tc, 5, attrs[2].ulValueLen);
+ CuAssertTrue (tc, memcmp (attrs[2].pValue, "disco", 5) == 0);
+
+ CuAssertTrue (tc, attrs[3].type == CKA_INVALID);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_merge_empty (CuTest *tc)
+{
+ CK_ATTRIBUTE extra[] = {
+ { CKA_LABEL, "boooyah", 7 },
+ { CKA_APPLICATION, "disco", 5 },
+ };
+
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_ATTRIBUTE *merge;
+
+ merge = p11_attrs_buildn (NULL, extra, 2);
+ attrs = p11_attrs_merge (attrs, merge, true);
+ CuAssertPtrNotNull (tc, attrs);
+ CuAssertPtrEquals (tc, merge, attrs);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_merge_augment (CuTest *tc)
+{
+ CK_ATTRIBUTE initial[] = {
+ { CKA_LABEL, "label", 5 },
+ { CKA_VALUE, "nine", 4 },
+ };
+
+ CK_ATTRIBUTE extra[] = {
+ { CKA_LABEL, "boooyah", 7 },
+ { CKA_APPLICATION, "disco", 5 },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *merge;
+
+ attrs = p11_attrs_buildn (NULL, initial, 2);
+ merge = p11_attrs_buildn (NULL, extra, 2);
+ attrs = p11_attrs_merge (attrs, merge, false);
+ CuAssertPtrNotNull (tc, attrs);
+
+ CuAssertTrue (tc, attrs[0].type == CKA_LABEL);
+ CuAssertIntEquals (tc, 5, attrs[0].ulValueLen);
+ CuAssertTrue (tc, memcmp (attrs[0].pValue, "label", 5) == 0);
+
+ CuAssertPtrNotNull (tc, attrs);
+ CuAssertTrue (tc, attrs[1].type == CKA_VALUE);
+ CuAssertIntEquals (tc, 4, attrs[1].ulValueLen);
+ CuAssertTrue (tc, memcmp (attrs[1].pValue, "nine", 4) == 0);
+
+ CuAssertPtrNotNull (tc, attrs);
+ CuAssertTrue (tc, attrs[2].type == CKA_APPLICATION);
+ CuAssertIntEquals (tc, 5, attrs[2].ulValueLen);
+ CuAssertTrue (tc, memcmp (attrs[2].pValue, "disco", 5) == 0);
+
+ CuAssertTrue (tc, attrs[3].type == CKA_INVALID);
+
+ p11_attrs_free (attrs);
+}
+
static void
test_free_null (CuTest *tc)
{
@@ -592,6 +692,9 @@ main (void)
SUITE_ADD_TEST (suite, test_build_null);
SUITE_ADD_TEST (suite, test_dup);
SUITE_ADD_TEST (suite, test_take);
+ SUITE_ADD_TEST (suite, test_merge_replace);
+ SUITE_ADD_TEST (suite, test_merge_augment);
+ SUITE_ADD_TEST (suite, test_merge_empty);
SUITE_ADD_TEST (suite, test_free_null);
SUITE_ADD_TEST (suite, test_match);
SUITE_ADD_TEST (suite, test_matchn);