summaryrefslogtreecommitdiff
path: root/trust
diff options
context:
space:
mode:
authorStef Walter <stef@thewalter.net>2013-06-26 13:16:42 +0200
committerStef Walter <stef@thewalter.net>2013-06-26 13:16:42 +0200
commit1e777512e554db76ba2f1aba800ee09a9fa074f0 (patch)
tree091b9d079edc3dd6a29fd1be8e470204c1e1a7f4 /trust
parentc807b2432bb954caf89f3092b65ea61a1bc6942e (diff)
trust: Implement validation for creating/modifying objects
Diffstat (limited to 'trust')
-rw-r--r--trust/builder.c277
-rw-r--r--trust/tests/test-builder.c427
2 files changed, 661 insertions, 43 deletions
diff --git a/trust/builder.c b/trust/builder.c
index 698fef1..bfbc42d 100644
--- a/trust/builder.c
+++ b/trust/builder.c
@@ -47,6 +47,7 @@
#include "message.h"
#include "oid.h"
#include "pkcs11x.h"
+#include "utf8.h"
#include "x509.h"
#include <assert.h>
@@ -77,8 +78,10 @@ typedef struct {
struct {
CK_ATTRIBUTE_TYPE type;
int flags;
+ bool (*validate) (p11_builder *, CK_ATTRIBUTE *);
} attrs[32];
CK_ATTRIBUTE * (*populate) (p11_builder *, p11_index *, CK_ATTRIBUTE *);
+ CK_RV (*validate) (p11_builder *, CK_ATTRIBUTE *);
} builder_schema;
static node_asn *
@@ -185,12 +188,140 @@ p11_builder_new (int flags)
return builder;
}
+static int
+atoin (const char *p,
+ int digits)
+{
+ int ret = 0, base = 1;
+ while(--digits >= 0) {
+ if (p[digits] < '0' || p[digits] > '9')
+ return -1;
+ ret += (p[digits] - '0') * base;
+ base *= 10;
+ }
+ return ret;
+}
+
+static bool
+type_bool (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ return (attr->pValue != NULL &&
+ sizeof (CK_BBOOL) == attr->ulValueLen);
+}
+
+static bool
+type_ulong (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ return (attr->pValue != NULL &&
+ sizeof (CK_ULONG) == attr->ulValueLen);
+}
+
+static bool
+type_utf8 (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ if (attr->ulValueLen == 0)
+ return true;
+ if (attr->pValue == NULL)
+ return false;
+ return p11_utf8_validate (attr->pValue, attr->ulValueLen);
+}
+
+static bool
+type_date (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ CK_DATE *date;
+ struct tm tm;
+ struct tm two;
+
+ if (attr->ulValueLen == 0)
+ return true;
+ if (attr->pValue == NULL || attr->ulValueLen != sizeof (CK_DATE))
+ return false;
+
+ date = attr->pValue;
+ memset (&tm, 0, sizeof (tm));
+ tm.tm_year = atoin ((char *)date->year, 4);
+ tm.tm_mon = atoin ((char *)date->month, 2);
+ tm.tm_mday = atoin ((char *)date->day, 2);
+
+ if (tm.tm_year < 0 || tm.tm_mon <= 0 || tm.tm_mday <= 0)
+ return false;
+
+ memcpy (&two, &tm, sizeof (tm));
+ if (mktime (&two) < 0)
+ return false;
+
+ /* If mktime changed anything, then bad date */
+ if (tm.tm_year != two.tm_year ||
+ tm.tm_mon != two.tm_mon ||
+ tm.tm_mday != two.tm_mday)
+ return false;
+
+ return true;
+}
+
+static bool
+check_der_struct (p11_builder *builder,
+ const char *struct_name,
+ CK_ATTRIBUTE *attr)
+{
+ node_asn *asn;
+
+ if (attr->ulValueLen == 0)
+ return true;
+ if (attr->pValue == NULL)
+ return false;
+
+ asn = p11_asn1_decode (builder->asn1_defs, struct_name,
+ attr->pValue, attr->ulValueLen, NULL);
+
+ if (asn == NULL)
+ return false;
+
+ asn1_delete_structure (&asn);
+ return true;
+}
+
+static bool
+type_der_name (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ return check_der_struct (builder, "PKIX1.Name", attr);
+}
+
+static bool
+type_der_serial (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ return check_der_struct (builder, "PKIX1.CertificateSerialNumber", attr);
+}
+
+static bool
+type_der_oid (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ /* AttributeType is an OBJECT ID */
+ return check_der_struct (builder, "PKIX1.AttributeType", attr);
+}
+
+static bool
+type_der_cert (p11_builder *builder,
+ CK_ATTRIBUTE *attr)
+{
+ /* AttributeType is an OBJECT ID */
+ return check_der_struct (builder, "PKIX1.Certificate", attr);
+}
+
#define COMMON_ATTRS \
- { CKA_CLASS, REQUIRE | CREATE }, \
- { CKA_TOKEN, CREATE | WANT }, \
- { CKA_MODIFIABLE, CREATE | WANT }, \
- { CKA_PRIVATE, CREATE }, \
- { CKA_LABEL, CREATE | MODIFY | WANT }, \
+ { CKA_CLASS, REQUIRE | CREATE, type_ulong }, \
+ { CKA_TOKEN, CREATE | WANT, type_bool }, \
+ { CKA_MODIFIABLE, CREATE | WANT, type_bool }, \
+ { CKA_PRIVATE, CREATE, type_bool }, \
+ { CKA_LABEL, CREATE | MODIFY | WANT, type_utf8 }, \
{ CKA_X_GENERATED, CREATE }
static CK_ATTRIBUTE *
@@ -228,20 +359,6 @@ calc_check_value (const unsigned char *data,
}
static int
-atoin (const char *p,
- int digits)
-{
- int ret = 0, base = 1;
- while(--digits >= 0) {
- if (p[digits] < '0' || p[digits] > '9')
- return -1;
- ret += (p[digits] - '0') * base;
- base *= 10;
- }
- return ret;
-}
-
-static int
century_for_two_digit_year (int year)
{
time_t now;
@@ -577,27 +694,58 @@ certificate_populate (p11_builder *builder,
return p11_attrs_build (attrs, &category, &empty_value, NULL);
}
+static CK_RV
+certificate_validate (p11_builder *builder,
+ CK_ATTRIBUTE *attrs)
+{
+ CK_ATTRIBUTE *attr;
+
+ /*
+ * In theory we should be validating that in the absence of CKA_VALUE
+ * various other fields must be set. However we do not enforce this
+ * because we want to be able to have certificates without a value
+ * but issuer and serial number, for blacklisting purposes.
+ */
+
+ attr = p11_attrs_find (attrs, CKA_URL);
+ if (attr != NULL && attr->ulValueLen > 0) {
+ attr = p11_attrs_find (attrs, CKA_HASH_OF_SUBJECT_PUBLIC_KEY);
+ if (attr == NULL || attr->ulValueLen == 0) {
+ p11_message ("missing the CKA_HASH_OF_SUBJECT_PUBLIC_KEY attribute");
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ attr = p11_attrs_find (attrs, CKA_HASH_OF_ISSUER_PUBLIC_KEY);
+ if (attr == NULL || attr->ulValueLen == 0) {
+ p11_message ("missing the CKA_HASH_OF_ISSUER_PUBLIC_KEY attribute");
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+
+ return CKR_OK;
+}
+
const static builder_schema certificate_schema = {
NORMAL_BUILD,
{ COMMON_ATTRS,
- { CKA_CERTIFICATE_TYPE, REQUIRE | CREATE },
- { CKA_TRUSTED, },
- { CKA_X_DISTRUSTED, },
- { CKA_CERTIFICATE_CATEGORY, CREATE | MODIFY | WANT },
- { CKA_CHECK_VALUE, CREATE | MODIFY | WANT },
- { CKA_START_DATE, CREATE | MODIFY | WANT },
- { CKA_END_DATE, CREATE | MODIFY | WANT },
- { CKA_SUBJECT, CREATE | WANT },
+ { CKA_CERTIFICATE_TYPE, REQUIRE | CREATE, type_ulong },
+ { CKA_TRUSTED, NONE, type_bool },
+ { CKA_X_DISTRUSTED, NONE, type_bool },
+ { CKA_CERTIFICATE_CATEGORY, CREATE | WANT, type_ulong },
+ { CKA_CHECK_VALUE, CREATE | WANT, },
+ { CKA_START_DATE, CREATE | MODIFY | WANT, type_date },
+ { CKA_END_DATE, CREATE | MODIFY | WANT, type_date },
+ { CKA_SUBJECT, CREATE | WANT, type_der_name },
{ CKA_ID, CREATE | MODIFY | WANT },
- { CKA_ISSUER, CREATE | MODIFY | WANT },
- { CKA_SERIAL_NUMBER, CREATE | MODIFY | WANT },
- { CKA_VALUE, CREATE },
- { CKA_URL, CREATE },
+ { CKA_ISSUER, CREATE | MODIFY | WANT, type_der_name },
+ { CKA_SERIAL_NUMBER, CREATE | MODIFY | WANT, type_der_serial },
+ { CKA_VALUE, CREATE, type_der_cert },
+ { CKA_URL, CREATE, type_utf8 },
{ CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CREATE },
{ CKA_HASH_OF_ISSUER_PUBLIC_KEY, CREATE },
- { CKA_JAVA_MIDP_SECURITY_DOMAIN, CREATE },
+ { CKA_JAVA_MIDP_SECURITY_DOMAIN, CREATE, type_ulong },
{ CKA_INVALID },
- }, certificate_populate,
+ }, certificate_populate, certificate_validate,
};
static CK_ATTRIBUTE *
@@ -624,8 +772,8 @@ const static builder_schema extension_schema = {
NORMAL_BUILD,
{ COMMON_ATTRS,
{ CKA_VALUE, REQUIRE | CREATE },
- { CKA_X_CRITICAL, WANT },
- { CKA_OBJECT_ID, REQUIRE | CREATE },
+ { CKA_X_CRITICAL, WANT, type_bool },
+ { CKA_OBJECT_ID, REQUIRE | CREATE, type_der_oid },
{ CKA_ID, CREATE | MODIFY | WANT },
{ CKA_INVALID },
}, extension_populate,
@@ -651,8 +799,8 @@ const static builder_schema data_schema = {
NORMAL_BUILD,
{ COMMON_ATTRS,
{ CKA_VALUE, CREATE | MODIFY | WANT },
- { CKA_APPLICATION, CREATE | MODIFY | WANT },
- { CKA_OBJECT_ID, CREATE | MODIFY | WANT },
+ { CKA_APPLICATION, CREATE | MODIFY | WANT, type_utf8 },
+ { CKA_OBJECT_ID, CREATE | MODIFY | WANT, type_der_oid },
{ CKA_INVALID },
}, data_populate,
};
@@ -749,6 +897,40 @@ type_name (CK_ATTRIBUTE_TYPE type)
}
static CK_RV
+validate_for_schema (p11_builder *builder,
+ const builder_schema *schema,
+ CK_ATTRIBUTE *attrs,
+ CK_ATTRIBUTE *merge)
+{
+ CK_ATTRIBUTE *shallow;
+ CK_ULONG nattrs;
+ CK_ULONG nmerge;
+ CK_RV rv;
+
+ if (!schema->validate)
+ return CKR_OK;
+
+ nattrs = p11_attrs_count (attrs);
+ nmerge = p11_attrs_count (merge);
+
+ /* Make a shallow copy of the combined attributes for validation */
+ shallow = calloc (nmerge + nattrs + 1, sizeof (CK_ATTRIBUTE));
+ return_val_if_fail (shallow != NULL, CKR_GENERAL_ERROR);
+
+ memcpy (shallow, merge, sizeof (CK_ATTRIBUTE) * nmerge);
+ memcpy (shallow + nmerge, attrs, sizeof (CK_ATTRIBUTE) * nattrs);
+
+ /* The terminator attribute */
+ shallow[nmerge + nattrs].type = CKA_INVALID;
+ assert(p11_attrs_terminator (shallow + nmerge + nattrs));
+
+ rv = (schema->validate) (builder, shallow);
+ free (shallow);
+
+ return rv;
+}
+
+static CK_RV
build_for_schema (p11_builder *builder,
p11_index *index,
const builder_schema *schema,
@@ -765,6 +947,7 @@ build_for_schema (p11_builder *builder,
bool found;
int flags;
int i, j;
+ CK_RV rv;
attrs = *object;
populate = false;
@@ -813,6 +996,12 @@ build_for_schema (p11_builder *builder,
type_name (schema->attrs[j].type));
return CKR_ATTRIBUTE_READ_ONLY;
}
+ if (!loading && schema->attrs[j].validate != NULL &&
+ !schema->attrs[j].validate (builder, merge + i)) {
+ p11_message ("the %s attribute has an invalid value",
+ type_name (schema->attrs[j].type));
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
found = true;
break;
}
@@ -856,12 +1045,14 @@ build_for_schema (p11_builder *builder,
merge = p11_attrs_merge (merge, extra, false);
}
- /*
- * TODO: Validate the result, before committing to the change. We can
- * do this by doing a shallow copy of merge + attrs and then validating
- * that. Although there may be duplicate attributets, the validation
- * code will see the new ones because they're first.
- */
+ /* Validate the result, before committing to the change. */
+ if (!loading) {
+ rv = validate_for_schema (builder, schema, attrs, merge);
+ if (rv != CKR_OK) {
+ p11_attrs_free (merge);
+ return rv;
+ }
+ }
*object = p11_attrs_merge (attrs, merge, true);
return_val_if_fail (*object != NULL, CKR_HOST_MEMORY);
diff --git a/trust/tests/test-builder.c b/trust/tests/test-builder.c
index 891c722..91998fa 100644
--- a/trust/tests/test-builder.c
+++ b/trust/tests/test-builder.c
@@ -528,6 +528,416 @@ test_build_distant_end_date (void)
}
static void
+test_valid_bool (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_BBOOL value = CK_TRUE;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_PRIVATE, &value, sizeof (value) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_bool (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ input[0].pValue = "123";
+ input[0].ulValueLen = 3;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = sizeof (CK_BBOOL);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_valid_ulong (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_ULONG value = 2;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CERTIFICATE_CATEGORY, &value, sizeof (value) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_ulong (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CERTIFICATE_CATEGORY, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ input[0].pValue = "123";
+ input[0].ulValueLen = 3;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = sizeof (CK_ULONG);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_valid_utf8 (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_LABEL, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 0;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_utf8 (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_LABEL, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ input[0].pValue = "\xfex23";
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_valid_dates (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_DATE date;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_START_DATE, &date, sizeof (CK_DATE) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ memcpy (&date, "20001010", sizeof (date));
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+ attrs = NULL;
+
+ input[0].ulValueLen = 0;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_dates (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_DATE date;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_START_DATE, &date, sizeof (CK_DATE) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ memcpy (&date, "AAAABBCC", sizeof (date));
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ memcpy (&date, "20001580", sizeof (date));
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ input[0].pValue = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_valid_name (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 0;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+ attrs = NULL;
+
+ input[0].pValue = (void *)test_cacert3_ca_issuer;
+ input[0].ulValueLen = sizeof (test_cacert3_ca_issuer);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_name (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ input[0].pValue = "blah";
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_valid_serial (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_SERIAL_NUMBER, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 0;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+ attrs = NULL;
+
+ input[0].pValue = (void *)test_cacert3_ca_serial;
+ input[0].ulValueLen = sizeof (test_cacert3_ca_serial);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_serial (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_SERIAL_NUMBER, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ input[0].pValue = "blah";
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ input[0].pValue = (void *)test_cacert3_ca_subject;
+ input[0].ulValueLen = sizeof (test_cacert3_ca_subject);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_valid_cert (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_VALUE, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 0;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+ attrs = NULL;
+
+ input[0].pValue = (void *)test_cacert3_ca_der;
+ input[0].ulValueLen = sizeof (test_cacert3_ca_der);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_OK, rv);
+
+ p11_attrs_free (attrs);
+}
+
+static void
+test_invalid_cert (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_VALUE, NULL, 0 },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ input[0].pValue = "blah";
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ input[0].pValue = (void *)test_cacert3_ca_subject;
+ input[0].ulValueLen = sizeof (test_cacert3_ca_subject);
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ input[0].pValue = NULL;
+ input[0].ulValueLen = 4;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_ATTRIBUTE_VALUE_INVALID, rv);
+
+ p11_message_loud ();
+}
+
+static void
+test_invalid_schema (void)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_RV rv;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_URL, "http://blah", 11 },
+ { CKA_INVALID },
+ };
+
+ p11_message_quiet ();
+
+ /* Missing CKA_HASH_OF_SUBJECT_PUBLIC_KEY and CKA_HASH_OF_ISSUER_PUBLIC_KEY */
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ assert_num_eq (CKR_TEMPLATE_INCONSISTENT, rv);
+
+ p11_message_loud ();
+}
+
+static void
test_create_not_settable (void)
{
/*
@@ -1597,6 +2007,23 @@ main (int argc,
p11_test (test_build_certificate_bad_type, "/builder/build_certificate_bad_type");
p11_test (test_build_extension, "/builder/build_extension");
p11_test (test_build_distant_end_date, "/builder/build_distant_end_date");
+
+ p11_test (test_valid_bool, "/builder/valid-bool");
+ p11_test (test_valid_ulong, "/builder/valid-ulong");
+ p11_test (test_valid_utf8, "/builder/valid-utf8");
+ p11_test (test_valid_dates, "/builder/valid-date");
+ p11_test (test_valid_name, "/builder/valid-name");
+ p11_test (test_valid_serial, "/builder/valid-serial");
+ p11_test (test_valid_cert, "/builder/valid-cert");
+ p11_test (test_invalid_bool, "/builder/invalid-bool");
+ p11_test (test_invalid_ulong, "/builder/invalid-ulong");
+ p11_test (test_invalid_utf8, "/builder/invalid-utf8");
+ p11_test (test_invalid_dates, "/builder/invalid-date");
+ p11_test (test_invalid_name, "/builder/invalid-name");
+ p11_test (test_invalid_serial, "/builder/invalid-serial");
+ p11_test (test_invalid_cert, "/builder/invalid-cert");
+ p11_test (test_invalid_schema, "/builder/invalid-schema");
+
p11_test (test_create_not_settable, "/builder/create_not_settable");
p11_test (test_create_but_loadable, "/builder/create_but_loadable");
p11_test (test_create_unsupported, "/builder/create_unsupported");