diff options
-rw-r--r-- | common/attrs.c | 52 | ||||
-rw-r--r-- | common/attrs.h | 4 | ||||
-rw-r--r-- | common/tests/test-attrs.c | 103 |
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); |