summaryrefslogtreecommitdiff
path: root/trust
diff options
context:
space:
mode:
Diffstat (limited to 'trust')
-rw-r--r--trust/Makefile.am2
-rw-r--r--trust/adapter.c472
-rw-r--r--trust/builder.c1556
-rw-r--r--trust/builder.h (renamed from trust/adapter.h)36
-rw-r--r--trust/parser.c836
-rw-r--r--trust/parser.h45
-rw-r--r--trust/session.c7
-rw-r--r--trust/session.h2
-rw-r--r--trust/tests/Makefile.am1
-rw-r--r--trust/tests/test-builder.c1611
-rw-r--r--trust/tests/test-data.c2
-rw-r--r--trust/tests/test-module.c28
-rw-r--r--trust/tests/test-parser.c666
-rw-r--r--trust/tests/test-token.c58
-rw-r--r--trust/token.c21
15 files changed, 3593 insertions, 1750 deletions
diff --git a/trust/Makefile.am b/trust/Makefile.am
index af4d327..0f84205 100644
--- a/trust/Makefile.am
+++ b/trust/Makefile.am
@@ -11,7 +11,7 @@ INCLUDES = \
$(NULL)
MODULE_SRCS = \
- adapter.c adapter.h \
+ builder.c builder.h \
index.c index.h \
parser.c parser.h \
module.c module.h \
diff --git a/trust/adapter.c b/trust/adapter.c
deleted file mode 100644
index 08e4c78..0000000
--- a/trust/adapter.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright (C) 2012 Red Hat Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the
- * above copyright notice, this list of conditions and
- * the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * * The names of contributors to this software may not be
- * used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * Author: Stef Walter <stefw@redhat.com>
- */
-
-#include "config.h"
-
-#include "adapter.h"
-#include "attrs.h"
-#include "checksum.h"
-#include "dict.h"
-#define P11_DEBUG_FLAG P11_DEBUG_TRUST
-#include "debug.h"
-#include "library.h"
-#include "oid.h"
-#include "parser.h"
-#include "pkcs11.h"
-#include "pkcs11x.h"
-#include "x509.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-static CK_ATTRIBUTE *
-build_trust_object_ku (p11_parser *parser,
- p11_array *parsing,
- CK_ATTRIBUTE *object,
- CK_TRUST present)
-{
- unsigned char *data = NULL;
- unsigned int ku = 0;
- p11_dict *defs;
- size_t length;
- CK_TRUST defawlt;
- CK_ULONG i;
-
- struct {
- CK_ATTRIBUTE_TYPE type;
- unsigned int ku;
- } ku_attribute_map[] = {
- { CKA_TRUST_DIGITAL_SIGNATURE, P11_KU_DIGITAL_SIGNATURE },
- { CKA_TRUST_NON_REPUDIATION, P11_KU_NON_REPUDIATION },
- { CKA_TRUST_KEY_ENCIPHERMENT, P11_KU_KEY_ENCIPHERMENT },
- { CKA_TRUST_DATA_ENCIPHERMENT, P11_KU_DATA_ENCIPHERMENT },
- { CKA_TRUST_KEY_AGREEMENT, P11_KU_KEY_AGREEMENT },
- { CKA_TRUST_KEY_CERT_SIGN, P11_KU_KEY_CERT_SIGN },
- { CKA_TRUST_CRL_SIGN, P11_KU_CRL_SIGN },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE attrs[sizeof (ku_attribute_map)];
-
- defawlt = present;
-
- /* If blacklisted, don't even bother looking at extensions */
- if (present != CKT_NSS_NOT_TRUSTED)
- data = p11_parsing_get_extension (parser, parsing, P11_OID_KEY_USAGE, &length);
-
- if (data) {
- /*
- * If the certificate extension was missing, then *all* key
- * usages are to be set. If the extension was invalid, then
- * fail safe to none of the key usages.
- */
- defawlt = CKT_NSS_TRUST_UNKNOWN;
-
- defs = p11_parser_get_asn1_defs (parser);
- if (!p11_x509_parse_key_usage (defs, data, length, &ku))
- p11_message ("invalid key usage certificate extension");
- free (data);
- }
-
- for (i = 0; ku_attribute_map[i].type != CKA_INVALID; i++) {
- attrs[i].type = ku_attribute_map[i].type;
- if (data && (ku & ku_attribute_map[i].ku) == ku_attribute_map[i].ku) {
- attrs[i].pValue = &present;
- attrs[i].ulValueLen = sizeof (present);
- } else {
- attrs[i].pValue = &defawlt;
- attrs[i].ulValueLen = sizeof (defawlt);
- }
- }
-
- return p11_attrs_buildn (object, attrs, i);
-}
-
-static bool
-strv_to_dict (const char **array,
- p11_dict **dict)
-{
- int i;
-
- if (!array) {
- *dict = NULL;
- return true;
- }
-
- *dict = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL);
- return_val_if_fail (*dict != NULL, false);
-
- for (i = 0; array[i] != NULL; i++) {
- if (!p11_dict_set (*dict, (void *)array[i], (void *)array[i]))
- return_val_if_reached (false);
- }
-
- return true;
-}
-
-static CK_ATTRIBUTE *
-build_trust_object_eku (p11_parser *parser,
- p11_array *parsing,
- CK_ATTRIBUTE *object,
- CK_TRUST allow,
- const char **purposes,
- const char **rejects)
-{
- p11_dict *dict_purp;
- p11_dict *dict_rej;
- CK_TRUST neutral;
- CK_TRUST disallow;
- CK_ULONG i;
-
- struct {
- CK_ATTRIBUTE_TYPE type;
- const char *oid;
- } eku_attribute_map[] = {
- { CKA_TRUST_SERVER_AUTH, P11_OID_SERVER_AUTH_STR },
- { CKA_TRUST_CLIENT_AUTH, P11_OID_CLIENT_AUTH_STR },
- { CKA_TRUST_CODE_SIGNING, P11_OID_CODE_SIGNING_STR },
- { CKA_TRUST_EMAIL_PROTECTION, P11_OID_EMAIL_PROTECTION_STR },
- { CKA_TRUST_IPSEC_END_SYSTEM, P11_OID_IPSEC_END_SYSTEM_STR },
- { CKA_TRUST_IPSEC_TUNNEL, P11_OID_IPSEC_TUNNEL_STR },
- { CKA_TRUST_IPSEC_USER, P11_OID_IPSEC_USER_STR },
- { CKA_TRUST_TIME_STAMPING, P11_OID_TIME_STAMPING_STR },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE attrs[sizeof (eku_attribute_map)];
-
- if (!strv_to_dict (purposes, &dict_purp) ||
- !strv_to_dict (rejects, &dict_rej))
- return_val_if_reached (NULL);
-
- /* The neutral value is set if an purpose is not present */
- if (allow == CKT_NSS_NOT_TRUSTED)
- neutral = CKT_NSS_NOT_TRUSTED;
-
- /* If anything explicitly set, then neutral is unknown */
- else if (purposes || rejects)
- neutral = CKT_NSS_TRUST_UNKNOWN;
-
- /* Otherwise neutral will allow any purpose */
- else
- neutral = allow;
-
- /* The value set if a purpose is explictly rejected */
- disallow = CKT_NSS_NOT_TRUSTED;
-
- for (i = 0; eku_attribute_map[i].type != CKA_INVALID; i++) {
- attrs[i].type = eku_attribute_map[i].type;
- if (dict_rej && p11_dict_get (dict_rej, eku_attribute_map[i].oid)) {
- attrs[i].pValue = &disallow;
- attrs[i].ulValueLen = sizeof (disallow);
- } else if (dict_purp && p11_dict_get (dict_purp, eku_attribute_map[i].oid)) {
- attrs[i].pValue = &allow;
- attrs[i].ulValueLen = sizeof (allow);
- } else {
- attrs[i].pValue = &neutral;
- attrs[i].ulValueLen = sizeof (neutral);
- }
- }
-
- p11_dict_free (dict_purp);
- p11_dict_free (dict_rej);
-
- return p11_attrs_buildn (object, attrs, i);
-}
-
-static void
-build_nss_trust_object (p11_parser *parser,
- p11_array *parsing,
- CK_ATTRIBUTE *cert,
- CK_BBOOL trust,
- CK_BBOOL distrust,
- CK_BBOOL authority,
- const char **purposes,
- const char **rejects)
-{
- CK_ATTRIBUTE *object = NULL;
- CK_TRUST allow;
-
- CK_OBJECT_CLASS vclass = CKO_NSS_TRUST;
- CK_BYTE vsha1_hash[P11_CHECKSUM_SHA1_LENGTH];
- CK_BYTE vmd5_hash[P11_CHECKSUM_MD5_LENGTH];
- CK_BBOOL vfalse = CK_FALSE;
- CK_BBOOL vtrue = CK_TRUE;
-
- CK_ATTRIBUTE klass = { CKA_CLASS, &vclass, sizeof (vclass) };
- CK_ATTRIBUTE token = { CKA_TOKEN, &vtrue, sizeof (vtrue) };
- CK_ATTRIBUTE private = { CKA_PRIVATE, &vfalse, sizeof (vfalse) };
- CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) };
- CK_ATTRIBUTE invalid = { CKA_INVALID, };
-
- CK_ATTRIBUTE md5_hash = { CKA_CERT_MD5_HASH, vmd5_hash, sizeof (vmd5_hash) };
- CK_ATTRIBUTE sha1_hash = { CKA_CERT_SHA1_HASH, vsha1_hash, sizeof (vsha1_hash) };
-
- CK_ATTRIBUTE step_up_approved = { CKA_TRUST_STEP_UP_APPROVED, &vfalse, sizeof (vfalse) };
-
- CK_ATTRIBUTE_PTR label;
- CK_ATTRIBUTE_PTR id;
- CK_ATTRIBUTE_PTR der;
- CK_ATTRIBUTE_PTR subject;
- CK_ATTRIBUTE_PTR issuer;
- CK_ATTRIBUTE_PTR serial_number;
-
- /* Setup the hashes of the DER certificate value */
- der = p11_attrs_find (cert, CKA_VALUE);
- return_if_fail (der != NULL);
- p11_checksum_md5 (vmd5_hash, der->pValue, der->ulValueLen, NULL);
- p11_checksum_sha1 (vsha1_hash, der->pValue, der->ulValueLen, NULL);
-
- /* Copy all of the following attributes from certificate */
- id = p11_attrs_find (cert, CKA_ID);
- return_if_fail (id != NULL);
- subject = p11_attrs_find (cert, CKA_SUBJECT);
- return_if_fail (subject != NULL);
- issuer = p11_attrs_find (cert, CKA_ISSUER);
- return_if_fail (issuer != NULL);
- serial_number = p11_attrs_find (cert, CKA_SERIAL_NUMBER);
- return_if_fail (serial_number != NULL);
-
- /* Try to use the same label */
- label = p11_attrs_find (cert, CKA_LABEL);
- if (label == NULL)
- label = &invalid;
-
- object = p11_attrs_build (NULL, &klass, &token, &private, &modifiable, id, label,
- subject, issuer, serial_number, &md5_hash, &sha1_hash,
- &step_up_approved, NULL);
- return_if_fail (object != NULL);
-
- /* Calculate the default allow trust */
- if (distrust)
- allow = CKT_NSS_NOT_TRUSTED;
- else if (trust && authority)
- allow = CKT_NSS_TRUSTED_DELEGATOR;
- else if (trust)
- allow = CKT_NSS_TRUSTED;
- else
- allow = CKT_NSS_TRUST_UNKNOWN;
-
- object = build_trust_object_ku (parser, parsing, object, allow);
- return_if_fail (object != NULL);
-
- object = build_trust_object_eku (parser, parsing, object, allow, purposes, rejects);
- return_if_fail (object != NULL);
-
- if (!p11_array_push (parsing, object))
- return_if_reached ();
-}
-
-static void
-build_assertions (p11_parser *parser,
- p11_array *parsing,
- CK_ATTRIBUTE *cert,
- CK_X_ASSERTION_TYPE type,
- const char **oids)
-{
- CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION;
- CK_BBOOL vtrue = CK_TRUE;
- CK_BBOOL vfalse = CK_FALSE;
-
- CK_ATTRIBUTE klass = { CKA_CLASS, &assertion, sizeof (assertion) };
- CK_ATTRIBUTE token = { CKA_TOKEN, &vtrue, sizeof (vtrue) };
- CK_ATTRIBUTE private = { CKA_PRIVATE, &vfalse, sizeof (vfalse) };
- CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) };
- CK_ATTRIBUTE assertion_type = { CKA_X_ASSERTION_TYPE, &type, sizeof (type) };
- CK_ATTRIBUTE purpose = { CKA_X_PURPOSE, };
- CK_ATTRIBUTE invalid = { CKA_INVALID, };
-
- CK_ATTRIBUTE *issuer;
- CK_ATTRIBUTE *serial;
- CK_ATTRIBUTE *value;
- CK_ATTRIBUTE *label;
- CK_ATTRIBUTE *id;
- CK_ATTRIBUTE *object;
- int i;
-
- label = p11_attrs_find (cert, CKA_LABEL);
- if (label == NULL)
- label = &invalid;
-
- id = p11_attrs_find (cert, CKA_ID);
- issuer = p11_attrs_find (cert, CKA_ISSUER);
- serial = p11_attrs_find (cert, CKA_SERIAL_NUMBER);
- value = p11_attrs_find (cert, CKA_VALUE);
-
- return_if_fail (id != NULL && issuer != NULL && serial != NULL && value != NULL);
-
- for (i = 0; oids[i] != NULL; i++) {
- purpose.pValue = (void *)oids[i];
- purpose.ulValueLen = strlen (oids[i]);
-
- object = p11_attrs_build (NULL, &klass, &token, &private, &modifiable,
- id, label, &assertion_type, &purpose,
- issuer, serial, value, NULL);
- return_if_fail (object != NULL);
-
- if (!p11_array_push (parsing, object))
- return_if_reached ();
- }
-}
-
-static void
-build_trust_assertions (p11_parser *parser,
- p11_array *parsing,
- CK_ATTRIBUTE *cert,
- CK_BBOOL trust,
- CK_BBOOL distrust,
- CK_BBOOL authority,
- const char **purposes,
- const char **rejects)
-{
- const char *all_purposes[] = {
- P11_OID_SERVER_AUTH_STR,
- P11_OID_CLIENT_AUTH_STR,
- P11_OID_CODE_SIGNING_STR,
- P11_OID_EMAIL_PROTECTION_STR,
- P11_OID_IPSEC_END_SYSTEM_STR,
- P11_OID_IPSEC_TUNNEL_STR,
- P11_OID_IPSEC_USER_STR,
- P11_OID_TIME_STAMPING_STR,
- NULL,
- };
-
- /* Build assertions for anything that's explicitly rejected */
- if (rejects) {
- build_assertions (parser, parsing, cert,
- CKT_X_DISTRUSTED_CERTIFICATE, rejects);
- }
-
- if (distrust) {
- /*
- * Trust assertions are defficient in that they don't blacklist a certificate
- * for any purposes. So we just have to go wild and write out a bunch of
- * assertions for all our known purposes.
- */
- build_assertions (parser, parsing, cert,
- CKT_X_DISTRUSTED_CERTIFICATE, all_purposes);
- }
-
- /*
- * TODO: Build pinned certificate assertions. That is, trusted
- * certificates where not an authority.
- */
-
- if (trust && authority) {
- if (purposes) {
- /* If purposes explicitly set, then anchor for those purposes */
- build_assertions (parser, parsing, cert,
- CKT_X_ANCHORED_CERTIFICATE, purposes);
- } else {
- /* If purposes not-explicitly set, then anchor for all known */
- build_assertions (parser, parsing, cert,
- CKT_X_ANCHORED_CERTIFICATE, all_purposes);
- }
- }
-}
-
-void
-p11_adapter_build_objects (p11_parser *parser,
- p11_array *parsing)
-{
- CK_ATTRIBUTE *cert;
- CK_ULONG category;
- CK_BBOOL trust = CK_FALSE;
- CK_BBOOL distrust = CK_FALSE;
- CK_BBOOL authority = CK_FALSE;
- p11_array *purposes = NULL;
- p11_array *rejects = NULL;
- const char **purposev;
- const char **rejectv;
- unsigned char *data;
- p11_dict *defs;
- size_t length;
-
- cert = p11_parsing_get_certificate (parser, parsing);
- return_if_fail (cert != NULL);
-
- /*
- * We look up all this information in advance, since it's used
- * by the various adapter objects, and we don't have to parse
- * it multiple times.
- */
-
- if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &trust))
- trust = CK_FALSE;
- if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &distrust))
- distrust = CK_FALSE;
- if (p11_attrs_find_ulong (cert, CKA_CERTIFICATE_CATEGORY, &category) && category == 2)
- authority = CK_TRUE;
-
- if (!distrust) {
- data = p11_parsing_get_extension (parser, parsing, P11_OID_EXTENDED_KEY_USAGE, &length);
- if (data) {
- defs = p11_parser_get_asn1_defs (parser);
- purposes = p11_x509_parse_extended_key_usage (defs, data, length);
- if (purposes == NULL)
- p11_message ("invalid extended key usage certificate extension");
- free (data);
- }
-
- data = p11_parsing_get_extension (parser, parsing, P11_OID_OPENSSL_REJECT, &length);
- if (data) {
- defs = p11_parser_get_asn1_defs (parser);
- rejects = p11_x509_parse_extended_key_usage (defs, data, length);
- if (rejects == NULL)
- p11_message ("invalid reject key usage certificate extension");
- free (data);
- }
- }
-
- /* null-terminate these arrays and use as strv's */
- purposev = rejectv = NULL;
- if (rejects) {
- if (!p11_array_push (rejects, NULL))
- return_if_reached ();
- rejectv = (const char **)rejects->elem;
- }
- if (purposes) {
- if (!p11_array_push (purposes, NULL))
- return_if_reached ();
- purposev = (const char **)purposes->elem;
- }
-
- build_nss_trust_object (parser, parsing, cert, trust, distrust,
- authority, purposev, rejectv);
- build_trust_assertions (parser, parsing, cert, trust, distrust,
- authority, purposev, rejectv);
-
- p11_array_free (purposes);
- p11_array_free (rejects);
-}
diff --git a/trust/builder.c b/trust/builder.c
new file mode 100644
index 0000000..4397b9b
--- /dev/null
+++ b/trust/builder.c
@@ -0,0 +1,1556 @@
+/*
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+
+#define P11_DEBUG_FLAG P11_DEBUG_TRUST
+
+#include "array.h"
+#include "asn1.h"
+#include "attrs.h"
+#include "builder.h"
+#include "checksum.h"
+#include "constants.h"
+#include "debug.h"
+#include "index.h"
+#include "library.h"
+#include "oid.h"
+#include "pkcs11x.h"
+#include "x509.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct _p11_builder {
+ p11_asn1_cache *asn1_cache;
+ p11_dict *asn1_defs;
+ int flags;
+};
+
+enum {
+ NONE = 0,
+ CREATE = 1 << 0,
+ MODIFY = 1 << 1,
+ REQUIRE = 1 << 2,
+ WANT = 1 << 3,
+};
+
+enum {
+ NORMAL_BUILD = 0,
+ GENERATED_CLASS = 1 << 0,
+};
+
+typedef struct {
+ int build_flags;
+ struct {
+ CK_ATTRIBUTE_TYPE type;
+ int flags;
+ } attrs[32];
+ CK_ATTRIBUTE * (*populate) (p11_builder *, p11_index *, CK_ATTRIBUTE *);
+} builder_schema;
+
+static node_asn *
+decode_or_get_asn1 (p11_builder *builder,
+ const char *struct_name,
+ const unsigned char *der,
+ size_t length)
+{
+ node_asn *node;
+
+ node = p11_asn1_cache_get (builder->asn1_cache, struct_name, der, length);
+ if (node != NULL)
+ return node;
+
+ node = p11_asn1_decode (builder->asn1_defs, struct_name, der, length, NULL);
+ if (node != NULL)
+ p11_asn1_cache_take (builder->asn1_cache, node, struct_name, der, length);
+
+ return node;
+}
+
+static unsigned char *
+lookup_extension (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert,
+ const unsigned char *oid,
+ size_t *ext_len)
+{
+ CK_OBJECT_CLASS klass = CKO_X_CERTIFICATE_EXTENSION;
+ CK_OBJECT_HANDLE obj;
+ CK_ATTRIBUTE *attrs;
+ unsigned char *ext;
+ CK_ATTRIBUTE *value;
+ CK_ATTRIBUTE *id;
+ node_asn *node;
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_ID, },
+ { CKA_OBJECT_ID, (void *)oid, p11_oid_length (oid) },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_INVALID },
+ };
+
+ /* Look for a stapled certificate extension */
+ id = p11_attrs_find (cert, CKA_ID);
+ if (id != NULL) {
+ match[0].pValue = id->pValue;
+ match[0].ulValueLen = id->ulValueLen;
+
+ obj = p11_index_find (index, match);
+ attrs = p11_index_lookup (index, obj);
+ if (attrs != NULL) {
+ value = p11_attrs_find (attrs, CKA_VALUE);
+ return_val_if_fail (value != NULL, NULL);
+
+ *ext_len = value->ulValueLen;
+ ext = memdup (value->pValue, value->ulValueLen);
+ return_val_if_fail (ext != NULL, NULL);
+ return ext;
+ }
+ }
+
+ /* Couldn't find a parsed extension, so look in the current certificate */
+ value = p11_attrs_find (cert, CKA_VALUE);
+ if (value != NULL) {
+ node = decode_or_get_asn1 (builder, "PKIX1.Certificate",
+ value->pValue, value->ulValueLen);
+ return_val_if_fail (node != NULL, false);
+
+ return p11_x509_find_extension (node, oid, value->pValue,
+ value->ulValueLen, ext_len);
+ }
+
+ return NULL;
+}
+
+static CK_OBJECT_HANDLE *
+lookup_related (p11_index *index,
+ CK_OBJECT_CLASS klass,
+ CK_ATTRIBUTE *id)
+{
+ CK_ATTRIBUTE match[] = {
+ { CKA_ID, },
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_INVALID }
+ };
+
+ return_val_if_fail (id != NULL, NULL);
+
+ match[0].pValue = id->pValue;
+ match[0].ulValueLen = id->ulValueLen;
+
+ return p11_index_find_all (index, match);
+}
+
+p11_builder *
+p11_builder_new (int flags)
+{
+ p11_builder *builder;
+
+ builder = calloc (1, sizeof (p11_builder));
+ return_val_if_fail (builder != NULL, NULL);
+
+ builder->asn1_cache = p11_asn1_cache_new ();
+ return_val_if_fail (builder->asn1_cache, NULL);
+ builder->asn1_defs = p11_asn1_cache_defs (builder->asn1_cache);
+
+ builder->flags = flags;
+ return builder;
+}
+
+#define COMMON_ATTRS \
+ { CKA_CLASS, REQUIRE | CREATE }, \
+ { CKA_TOKEN, CREATE | WANT }, \
+ { CKA_MODIFIABLE, CREATE | WANT }, \
+ { CKA_PRIVATE, CREATE }, \
+ { CKA_LABEL, CREATE | MODIFY | WANT }, \
+ { CKA_X_GENERATED, CREATE }
+
+static CK_ATTRIBUTE *
+common_populate (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *unused)
+{
+ CK_BBOOL tokenv = CK_FALSE;
+ CK_BBOOL modifiablev = CK_TRUE;
+ CK_BBOOL privatev = CK_FALSE;
+ CK_BBOOL generatedv = CK_FALSE;
+
+ CK_ATTRIBUTE token = { CKA_TOKEN, &tokenv, sizeof (tokenv), };
+ CK_ATTRIBUTE privat = { CKA_PRIVATE, &privatev, sizeof (privatev) };
+ CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
+ CK_ATTRIBUTE generated = { CKA_X_GENERATED, &generatedv, sizeof (generatedv) };
+ CK_ATTRIBUTE label = { CKA_LABEL, "", 0 };
+
+ if (builder->flags & P11_BUILDER_FLAG_TOKEN) {
+ tokenv = CK_TRUE;
+ modifiablev = CK_FALSE;
+ }
+
+ return p11_attrs_build (NULL, &token, &privat, &modifiable, &label, &generated, NULL);
+}
+
+static void
+calc_check_value (const unsigned char *data,
+ size_t length,
+ CK_BYTE *check_value)
+{
+ unsigned char checksum[P11_CHECKSUM_SHA1_LENGTH];
+ p11_checksum_sha1 (checksum, data, length, NULL);
+ memcpy (check_value, checksum, 3);
+}
+
+static bool
+calc_date (node_asn *node,
+ const char *field,
+ CK_DATE *date)
+{
+ node_asn *choice;
+ struct tm when;
+ char buf[64];
+ time_t timet;
+ char *sub;
+ int len;
+ int ret;
+
+ if (!node)
+ return false;
+
+ choice = asn1_find_node (node, field);
+ return_val_if_fail (choice != NULL, false);
+
+ len = sizeof (buf) - 1;
+ ret = asn1_read_value (node, field, buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+
+ sub = strconcat (field, ".", buf, NULL);
+
+ if (strcmp (buf, "generalTime") == 0) {
+ len = sizeof (buf) - 1;
+ ret = asn1_read_value (node, sub, buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+ timet = p11_asn1_parse_general (buf, &when);
+ return_val_if_fail (timet >= 0, false);
+
+ } else if (strcmp (buf, "utcTime") == 0) {
+ len = sizeof (buf) - 1;
+ ret = asn1_read_value (node, sub, buf, &len);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+ timet = p11_asn1_parse_utc (buf, &when);
+ return_val_if_fail (timet >= 0, false);
+
+ } else {
+ return_val_if_reached (false);
+ }
+
+ free (sub);
+
+ assert (sizeof (date->year) == 4);
+ snprintf ((char *)buf, 5, "%04d", 1900 + when.tm_year);
+ memcpy (date->year, buf, 4);
+
+ assert (sizeof (date->month) == 2);
+ snprintf ((char *)buf, 3, "%02d", when.tm_mon + 1);
+ memcpy (date->month, buf, 2);
+
+ assert (sizeof (date->day) == 2);
+ snprintf ((char *)buf, 3, "%02d", when.tm_mday);
+ memcpy (date->day, buf, 2);
+
+ return true;
+}
+
+static bool
+calc_element (node_asn *node,
+ const unsigned char *data,
+ size_t length,
+ const char *field,
+ CK_ATTRIBUTE *attr)
+{
+ int ret;
+ int start, end;
+
+ if (!node)
+ return false;
+
+ ret = asn1_der_decoding_startEnd (node, data, length, field, &start, &end);
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+ return_val_if_fail (end >= start, false);
+
+ attr->pValue = (void *)(data + start);
+ attr->ulValueLen = (end - start) + 1;
+ return true;
+}
+
+static bool
+is_v1_x509_authority (p11_builder *builder,
+ CK_ATTRIBUTE *cert)
+{
+ CK_ATTRIBUTE subject;
+ CK_ATTRIBUTE issuer;
+ CK_ATTRIBUTE *value;
+ char buffer[16];
+ node_asn *node;
+ int len;
+ int ret;
+
+ value = p11_attrs_find_valid (cert, CKA_VALUE);
+ if (value == NULL)
+ return false;
+
+ node = decode_or_get_asn1 (builder, "PKIX1.Certificate",
+ value->pValue, value->ulValueLen);
+ return_val_if_fail (node != NULL, false);
+
+ len = sizeof (buffer);
+ ret = asn1_read_value (node, "tbsCertificate.version", buffer, &len);
+
+ /* The default value */
+ if (ret == ASN1_ELEMENT_NOT_FOUND) {
+ ret = ASN1_SUCCESS;
+ buffer[0] = 0;
+ len = 1;
+ }
+
+ return_val_if_fail (ret == ASN1_SUCCESS, false);
+
+ /*
+ * In X.509 version v1 is the integer zero. Two's complement
+ * integer, but zero is easy to read.
+ */
+ if (len != 1 || buffer[0] != 0)
+ return false;
+
+ /* Must be self-signed, ie: same subject and issuer */
+ if (!calc_element (node, value->pValue, value->ulValueLen, "tbsCertificate.subject", &subject))
+ return_val_if_reached (false);
+ if (!calc_element (node, value->pValue, value->ulValueLen, "tbsCertificate.issuer", &issuer))
+ return_val_if_reached (false);
+ return p11_attr_match_value (&subject, issuer.pValue, issuer.ulValueLen);
+}
+
+static bool
+calc_certificate_category (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert,
+ CK_ULONG *category)
+{
+ unsigned char *ext;
+ size_t ext_len;
+ bool is_ca = 0;
+ bool ret;
+
+ /*
+ * In the PKCS#11 spec:
+ * 0 = unspecified (default value)
+ * 1 = token user
+ * 2 = authority
+ * 3 = other entity
+ */
+
+ /* See if we have a basic constraints extension */
+ ext = lookup_extension (builder, index, cert, P11_OID_BASIC_CONSTRAINTS, &ext_len);
+ if (ext != NULL) {
+ ret = p11_x509_parse_basic_constraints (builder->asn1_defs, ext, ext_len, &is_ca);
+ free (ext);
+ if (!ret) {
+ p11_message ("invalid basic constraints certificate extension");
+ return false;
+ }
+
+ } else if (is_v1_x509_authority (builder, cert)) {
+ /*
+ * If there is no basic constraints extension, and the CA version is
+ * v1, and is self-signed, then we assume this is a certificate authority.
+ * So we add a BasicConstraints stapled certificate extension
+ */
+ is_ca = 1;
+
+ } else if (!p11_attrs_find_valid (cert, CKA_VALUE)) {
+ /*
+ * If we have no certificate value, then this is unknown
+ */
+ *category = 0;
+ return true;
+
+ }
+
+ *category = is_ca ? 2 : 3;
+ return true;
+}
+
+static CK_ATTRIBUTE *
+certificate_value_attrs (CK_ATTRIBUTE *attrs,
+ node_asn *node,
+ const unsigned char *der,
+ size_t der_len)
+{
+ CK_BBOOL falsev = CK_FALSE;
+ CK_ULONG zero = 0UL;
+ CK_BYTE checkv[3];
+ CK_DATE startv;
+ CK_DATE endv;
+ char *labelv = NULL;
+
+ CK_ATTRIBUTE trusted = { CKA_TRUSTED, &falsev, sizeof (falsev) };
+ CK_ATTRIBUTE distrusted = { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) };
+ CK_ATTRIBUTE url = { CKA_URL, "", 0 };
+ CK_ATTRIBUTE hash_of_subject_public_key = { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, "", 0 };
+ CK_ATTRIBUTE hash_of_issuer_public_key = { CKA_HASH_OF_ISSUER_PUBLIC_KEY, "", 0 };
+ CK_ATTRIBUTE java_midp_security_domain = { CKA_JAVA_MIDP_SECURITY_DOMAIN, &zero, sizeof (zero) };
+ CK_ATTRIBUTE check_value = { CKA_CHECK_VALUE, &checkv, sizeof (checkv) };
+ CK_ATTRIBUTE start_date = { CKA_START_DATE, &startv, sizeof (startv) };
+ CK_ATTRIBUTE end_date = { CKA_END_DATE, &endv, sizeof (endv) };
+ CK_ATTRIBUTE subject = { CKA_SUBJECT, };
+ CK_ATTRIBUTE issuer = { CKA_ISSUER, "", 0 };
+ CK_ATTRIBUTE serial_number = { CKA_SERIAL_NUMBER, "", 0 };
+ CK_ATTRIBUTE label = { CKA_LABEL };
+
+ return_val_if_fail (attrs != NULL, NULL);
+
+ if (der == NULL)
+ check_value.type = CKA_INVALID;
+ else
+ calc_check_value (der, der_len, checkv);
+
+ if (!calc_date (node, "tbsCertificate.validity.notBefore", &startv))
+ start_date.ulValueLen = 0;
+ if (!calc_date (node, "tbsCertificate.validity.notAfter", &endv))
+ end_date.ulValueLen = 0;
+
+ calc_element (node, der, der_len, "tbsCertificate.issuer.rdnSequence", &issuer);
+ if (!calc_element (node, der, der_len, "tbsCertificate.subject.rdnSequence", &subject))
+ subject.type = CKA_INVALID;
+ calc_element (node, der, der_len, "tbsCertificate.serialNumber", &serial_number);
+
+ if (node) {
+ labelv = p11_x509_lookup_dn_name (node, "tbsCertificate.subject",
+ der, der_len, P11_OID_CN);
+ if (!labelv)
+ labelv = p11_x509_lookup_dn_name (node, "tbsCertificate.subject",
+ der, der_len, P11_OID_OU);
+ if (!labelv)
+ labelv = p11_x509_lookup_dn_name (node, "tbsCertificate.subject",
+ der, der_len, P11_OID_O);
+ }
+
+ if (labelv) {
+ label.pValue = labelv;
+ label.ulValueLen = strlen (labelv);
+ } else {
+ label.type = CKA_INVALID;
+ }
+
+ attrs = p11_attrs_build (attrs, &trusted, &distrusted, &url, &hash_of_issuer_public_key,
+ &hash_of_subject_public_key, &java_midp_security_domain,
+ &check_value, &start_date, &end_date,
+ &subject, &issuer, &serial_number, &label,
+ NULL);
+ return_val_if_fail (attrs != NULL, NULL);
+
+ return attrs;
+}
+
+static CK_ATTRIBUTE *
+certificate_populate (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert)
+{
+ CK_ULONG categoryv = 0UL;
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_ATTRIBUTE *value;
+ node_asn *node = NULL;
+ unsigned char *der = NULL;
+ size_t der_len = 0;
+
+ CK_ATTRIBUTE category = { CKA_CERTIFICATE_CATEGORY, &categoryv, sizeof (categoryv) };
+ CK_ATTRIBUTE empty_value = { CKA_VALUE, "", 0 };
+
+ attrs = common_populate (builder, index, cert);
+ return_val_if_fail (attrs != NULL, NULL);
+
+ value = p11_attrs_find_valid (cert, CKA_VALUE);
+ if (value != NULL) {
+ der = value->pValue;
+ der_len = value->ulValueLen;
+ node = decode_or_get_asn1 (builder, "PKIX1.Certificate",
+ value->pValue, value->ulValueLen);
+ }
+
+ attrs = certificate_value_attrs (attrs, node, der, der_len);
+ return_val_if_fail (attrs != NULL, NULL);
+
+ if (!calc_certificate_category (builder, index, cert, &categoryv))
+ categoryv = 0;
+
+ return p11_attrs_build (attrs, &category, &empty_value, NULL);
+}
+
+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_ID, CREATE | MODIFY | WANT },
+ { CKA_ISSUER, CREATE | MODIFY | WANT },
+ { CKA_SERIAL_NUMBER, CREATE | MODIFY | WANT },
+ { CKA_VALUE, CREATE },
+ { CKA_URL, CREATE },
+ { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, CREATE },
+ { CKA_HASH_OF_ISSUER_PUBLIC_KEY, CREATE },
+ { CKA_JAVA_MIDP_SECURITY_DOMAIN, CREATE },
+ { CKA_INVALID },
+ }, certificate_populate,
+};
+
+static CK_ATTRIBUTE *
+extension_populate (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *extension)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+
+ attrs = common_populate (builder, index, extension);
+ return_val_if_fail (attrs != NULL, NULL);
+
+ if (!p11_attrs_find_valid (extension, CKA_X_CRITICAL)) {
+ CK_BBOOL falsev = CK_FALSE;
+ CK_ATTRIBUTE critical = { CKA_X_CRITICAL, &falsev, sizeof (falsev) };
+ attrs = p11_attrs_build (attrs, &critical, NULL);
+ return_val_if_fail (attrs != NULL, NULL);
+ }
+
+ return attrs;
+}
+
+const static builder_schema extension_schema = {
+ NORMAL_BUILD,
+ { COMMON_ATTRS,
+ { CKA_VALUE, REQUIRE | CREATE },
+ { CKA_X_CRITICAL, WANT },
+ { CKA_OBJECT_ID, REQUIRE | CREATE },
+ { CKA_ID, CREATE | MODIFY | WANT },
+ { CKA_INVALID },
+ }, extension_populate,
+};
+
+static CK_ATTRIBUTE *
+data_populate (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *data)
+{
+ static CK_ATTRIBUTE value = { CKA_VALUE, "", 0 };
+ static CK_ATTRIBUTE application = { CKA_APPLICATION, "", 0 };
+ static CK_ATTRIBUTE object_id = { CKA_OBJECT_ID, "", 0 };
+ CK_ATTRIBUTE *attrs;
+
+ attrs = common_populate (builder, index, data);
+ return_val_if_fail (attrs != NULL, NULL);
+
+ return p11_attrs_build (attrs, &value, &application, &object_id, NULL);
+}
+
+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_INVALID },
+ }, data_populate,
+};
+
+const static builder_schema trust_schema = {
+ GENERATED_CLASS,
+ { COMMON_ATTRS,
+ { CKA_CERT_SHA1_HASH, CREATE },
+ { CKA_CERT_MD5_HASH, CREATE },
+ { CKA_ISSUER, CREATE },
+ { CKA_SUBJECT, CREATE },
+ { CKA_SERIAL_NUMBER, CREATE },
+ { CKA_TRUST_SERVER_AUTH, CREATE },
+ { CKA_TRUST_CLIENT_AUTH, CREATE },
+ { CKA_TRUST_EMAIL_PROTECTION, CREATE },
+ { CKA_TRUST_CODE_SIGNING, CREATE },
+ { CKA_TRUST_IPSEC_END_SYSTEM, CREATE },
+ { CKA_TRUST_IPSEC_TUNNEL, CREATE },
+ { CKA_TRUST_IPSEC_USER, CREATE },
+ { CKA_TRUST_TIME_STAMPING, CREATE },
+ { CKA_TRUST_DIGITAL_SIGNATURE, CREATE },
+ { CKA_TRUST_NON_REPUDIATION, CREATE },
+ { CKA_TRUST_KEY_ENCIPHERMENT, CREATE },
+ { CKA_TRUST_DATA_ENCIPHERMENT, CREATE },
+ { CKA_TRUST_KEY_AGREEMENT, CREATE },
+ { CKA_TRUST_KEY_CERT_SIGN, CREATE },
+ { CKA_TRUST_CRL_SIGN, CREATE },
+ { CKA_TRUST_STEP_UP_APPROVED, CREATE },
+ { CKA_ID, CREATE },
+ { CKA_INVALID },
+ }, common_populate
+};
+
+const static builder_schema assertion_schema = {
+ GENERATED_CLASS,
+ { COMMON_ATTRS,
+ { CKA_X_PURPOSE, REQUIRE | CREATE },
+ { CKA_VALUE, CREATE },
+ { CKA_X_ASSERTION_TYPE, REQUIRE | CREATE },
+ { CKA_ISSUER, CREATE },
+ { CKA_SERIAL_NUMBER, CREATE },
+ { CKA_X_PEER, CREATE },
+ { CKA_ID, CREATE },
+ { CKA_INVALID },
+ }, common_populate
+};
+
+const static builder_schema builtin_schema = {
+ GENERATED_CLASS,
+ { COMMON_ATTRS,
+ { CKA_INVALID },
+ }, common_populate
+};
+
+static void
+attrs_filter_if_unchanged (CK_ATTRIBUTE *attrs,
+ CK_ATTRIBUTE *merge)
+{
+ CK_ATTRIBUTE *attr;
+ int in, out;
+
+ assert (attrs != NULL);
+ assert (merge != NULL);
+
+ for (in = 0, out = 0; !p11_attrs_is_empty (merge + in); in++) {
+ attr = p11_attrs_find (attrs, merge[in].type);
+ if (attr && p11_attr_equal (attr, merge + in)) {
+ free (merge[in].pValue);
+ merge[in].pValue = NULL;
+ merge[in].ulValueLen = 0;
+ } else {
+ if (in != out)
+ memcpy (merge + out, merge + in, sizeof (CK_ATTRIBUTE));
+ out++;
+ }
+ }
+
+ merge[out].type = CKA_INVALID;
+ assert (p11_attrs_is_empty (merge + out));
+}
+
+static const char *
+value_name (const p11_constant *info,
+ CK_ATTRIBUTE_TYPE type)
+{
+ const char *name = p11_constant_name (info, type);
+ return name ? name : "unknown";
+}
+
+static const char *
+type_name (CK_ATTRIBUTE_TYPE type)
+{
+ return value_name (p11_constant_types, type);
+}
+
+static CK_RV
+build_for_schema (p11_builder *builder,
+ p11_index *index,
+ const builder_schema *schema,
+ CK_ATTRIBUTE **object,
+ CK_ATTRIBUTE *merge)
+{
+ CK_ATTRIBUTE *extra;
+ CK_ATTRIBUTE *attrs;
+ CK_BBOOL modifiable;
+ bool modifying;
+ bool creating;
+ bool populate;
+ bool loading;
+ bool found;
+ int flags;
+ int i, j;
+
+ attrs = *object;
+ populate = false;
+
+ /* Signifies that data is being loaded */
+ loading = p11_index_in_batch (index);
+
+ /* Signifies that this is being created by a caller, instead of loaded */
+ creating = (attrs == NULL && !loading);
+
+ /* Item is being modified by a caller */
+ modifying = (attrs != NULL && !loading);
+
+ /* This item may not be modifiable */
+ if (modifying) {
+ if (!p11_attrs_find_bool (attrs, CKA_MODIFIABLE, &modifiable) || !modifiable) {
+ p11_message ("the object is not modifiable");
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ }
+
+ if (attrs != NULL)
+ attrs_filter_if_unchanged (attrs, merge);
+
+ if (creating) {
+ if (schema->build_flags & GENERATED_CLASS) {
+ p11_message ("objects of this type cannot be created");
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+
+ for (i = 0; merge[i].type != CKA_INVALID; i++) {
+ found = false;
+ for (j = 0; schema->attrs[j].type != CKA_INVALID; j++) {
+ if (schema->attrs[j].type != merge[i].type)
+ continue;
+
+ flags = schema->attrs[j].flags;
+ if (creating && !(flags & CREATE)) {
+ p11_message ("the %s attribute cannot be set",
+ type_name (schema->attrs[j].type));
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ if (modifying && !(flags & MODIFY)) {
+ p11_message ("the %s attribute cannot be changed",
+ type_name (schema->attrs[j].type));
+ return CKR_ATTRIBUTE_READ_ONLY;
+ }
+ found = true;
+ break;
+ }
+
+ if (!found) {
+ p11_message ("the %s attribute is not valid for the object",
+ type_name (merge[i].type));
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+
+ if (attrs == NULL) {
+ for (j = 0; schema->attrs[j].type != CKA_INVALID; j++) {
+ flags = schema->attrs[j].flags;
+ found = false;
+
+ if ((flags & REQUIRE) || (flags & WANT)) {
+ for (i = 0; merge[i].type != CKA_INVALID; i++) {
+ if (schema->attrs[j].type == merge[i].type) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ if (flags & REQUIRE) {
+ p11_message ("missing the %s attribute",
+ type_name (schema->attrs[j].type));
+ return CKR_TEMPLATE_INCOMPLETE;
+ } else if (flags & WANT) {
+ populate = true;
+ }
+ }
+ }
+ }
+
+ if (populate && schema->populate) {
+ extra = schema->populate (builder, index, merge);
+ if (extra != NULL)
+ 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.
+ */
+
+ *object = p11_attrs_merge (attrs, merge, true);
+ return_val_if_fail (*object != NULL, CKR_HOST_MEMORY);
+
+ return CKR_OK;
+}
+
+CK_RV
+p11_builder_build (void *bilder,
+ p11_index *index,
+ CK_ATTRIBUTE **object,
+ CK_ATTRIBUTE *merge)
+{
+ p11_builder *builder = bilder;
+ CK_ATTRIBUTE *attrs;
+ CK_OBJECT_CLASS klass;
+ CK_CERTIFICATE_TYPE type;
+ CK_BBOOL token;
+
+ return_val_if_fail (builder != NULL, CKR_GENERAL_ERROR);
+ return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
+ return_val_if_fail (merge != NULL, CKR_GENERAL_ERROR);
+
+ attrs = *object;
+
+ if (!p11_attrs_find_ulong (attrs ? attrs : merge, CKA_CLASS, &klass)) {
+ p11_message ("no CKA_CLASS attribute found");
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+
+ if (!attrs && p11_attrs_find_bool (merge, CKA_TOKEN, &token)) {
+ if (token != ((builder->flags & P11_BUILDER_FLAG_TOKEN) ? CK_TRUE : CK_FALSE)) {
+ p11_message ("cannot create a %s object", token ? "token" : "non-token");
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+ }
+
+ switch (klass) {
+ case CKO_CERTIFICATE:
+ if (!p11_attrs_find_ulong (attrs ? attrs : merge, CKA_CERTIFICATE_TYPE, &type)) {
+ p11_message ("missing %s on object", type_name (CKA_CERTIFICATE_TYPE));
+ return CKR_TEMPLATE_INCOMPLETE;
+ } else if (type == CKC_X_509) {
+ return build_for_schema (builder, index, &certificate_schema, object, merge);
+ } else {
+ p11_message ("%s unsupported %s", value_name (p11_constant_certs, type),
+ type_name (CKA_CERTIFICATE_TYPE));
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+
+ case CKO_X_CERTIFICATE_EXTENSION:
+ return build_for_schema (builder, index, &extension_schema, object, merge);
+
+ case CKO_DATA:
+ return build_for_schema (builder, index, &data_schema, object, merge);
+
+ case CKO_NSS_TRUST:
+ return build_for_schema (builder, index, &trust_schema, object, merge);
+
+ case CKO_NSS_BUILTIN_ROOT_LIST:
+ return build_for_schema (builder, index, &builtin_schema, object, merge);
+
+ case CKO_X_TRUST_ASSERTION:
+ return build_for_schema (builder, index, &assertion_schema, object, merge);
+
+ default:
+ p11_message ("%s unsupported object class",
+ value_name (p11_constant_classes, klass));
+ return CKR_TEMPLATE_INCONSISTENT;
+ }
+}
+
+void
+p11_builder_free (p11_builder *builder)
+{
+ return_if_fail (builder != NULL);
+
+ p11_asn1_cache_free (builder->asn1_cache);
+ free (builder);
+}
+
+p11_asn1_cache *
+p11_builder_get_cache (p11_builder *builder)
+{
+ return_val_if_fail (builder != NULL, NULL);
+ return builder->asn1_cache;
+}
+
+static CK_ATTRIBUTE *
+build_trust_object_ku (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert,
+ CK_ATTRIBUTE *object,
+ CK_TRUST present)
+{
+ unsigned char *data = NULL;
+ unsigned int ku = 0;
+ size_t length;
+ CK_TRUST defawlt;
+ CK_ULONG i;
+
+ struct {
+ CK_ATTRIBUTE_TYPE type;
+ unsigned int ku;
+ } ku_attribute_map[] = {
+ { CKA_TRUST_DIGITAL_SIGNATURE, P11_KU_DIGITAL_SIGNATURE },
+ { CKA_TRUST_NON_REPUDIATION, P11_KU_NON_REPUDIATION },
+ { CKA_TRUST_KEY_ENCIPHERMENT, P11_KU_KEY_ENCIPHERMENT },
+ { CKA_TRUST_DATA_ENCIPHERMENT, P11_KU_DATA_ENCIPHERMENT },
+ { CKA_TRUST_KEY_AGREEMENT, P11_KU_KEY_AGREEMENT },
+ { CKA_TRUST_KEY_CERT_SIGN, P11_KU_KEY_CERT_SIGN },
+ { CKA_TRUST_CRL_SIGN, P11_KU_CRL_SIGN },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE attrs[sizeof (ku_attribute_map)];
+
+ defawlt = present;
+
+ /* If blacklisted, don't even bother looking at extensions */
+ if (present != CKT_NSS_NOT_TRUSTED)
+ data = lookup_extension (builder, index, cert, P11_OID_KEY_USAGE, &length);
+
+ if (data) {
+ /*
+ * If the certificate extension was missing, then *all* key
+ * usages are to be set. If the extension was invalid, then
+ * fail safe to none of the key usages.
+ */
+ defawlt = CKT_NSS_TRUST_UNKNOWN;
+
+ if (!p11_x509_parse_key_usage (builder->asn1_defs, data, length, &ku))
+ p11_message ("invalid key usage certificate extension");
+ free (data);
+ }
+
+ for (i = 0; ku_attribute_map[i].type != CKA_INVALID; i++) {
+ attrs[i].type = ku_attribute_map[i].type;
+ if (data && (ku & ku_attribute_map[i].ku) == ku_attribute_map[i].ku) {
+ attrs[i].pValue = &present;
+ attrs[i].ulValueLen = sizeof (present);
+ } else {
+ attrs[i].pValue = &defawlt;
+ attrs[i].ulValueLen = sizeof (defawlt);
+ }
+ }
+
+ return p11_attrs_buildn (object, attrs, i);
+}
+
+static bool
+strv_to_dict (const char **array,
+ p11_dict **dict)
+{
+ int i;
+
+ if (!array) {
+ *dict = NULL;
+ return true;
+ }
+
+ *dict = p11_dict_new (p11_dict_str_hash, p11_dict_str_equal, NULL, NULL);
+ return_val_if_fail (*dict != NULL, false);
+
+ for (i = 0; array[i] != NULL; i++) {
+ if (!p11_dict_set (*dict, (void *)array[i], (void *)array[i]))
+ return_val_if_reached (false);
+ }
+
+ return true;
+}
+
+static CK_ATTRIBUTE *
+build_trust_object_eku (CK_ATTRIBUTE *object,
+ CK_TRUST allow,
+ const char **purposes,
+ const char **rejects)
+{
+ p11_dict *dict_purp;
+ p11_dict *dict_rej;
+ CK_TRUST neutral;
+ CK_TRUST disallow;
+ CK_ULONG i;
+
+ struct {
+ CK_ATTRIBUTE_TYPE type;
+ const char *oid;
+ } eku_attribute_map[] = {
+ { CKA_TRUST_SERVER_AUTH, P11_OID_SERVER_AUTH_STR },
+ { CKA_TRUST_CLIENT_AUTH, P11_OID_CLIENT_AUTH_STR },
+ { CKA_TRUST_CODE_SIGNING, P11_OID_CODE_SIGNING_STR },
+ { CKA_TRUST_EMAIL_PROTECTION, P11_OID_EMAIL_PROTECTION_STR },
+ { CKA_TRUST_IPSEC_END_SYSTEM, P11_OID_IPSEC_END_SYSTEM_STR },
+ { CKA_TRUST_IPSEC_TUNNEL, P11_OID_IPSEC_TUNNEL_STR },
+ { CKA_TRUST_IPSEC_USER, P11_OID_IPSEC_USER_STR },
+ { CKA_TRUST_TIME_STAMPING, P11_OID_TIME_STAMPING_STR },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE attrs[sizeof (eku_attribute_map)];
+
+ if (!strv_to_dict (purposes, &dict_purp) ||
+ !strv_to_dict (rejects, &dict_rej))
+ return_val_if_reached (NULL);
+
+ /* The neutral value is set if an purpose is not present */
+ if (allow == CKT_NSS_NOT_TRUSTED)
+ neutral = CKT_NSS_NOT_TRUSTED;
+
+ /* If anything explicitly set, then neutral is unknown */
+ else if (purposes || rejects)
+ neutral = CKT_NSS_TRUST_UNKNOWN;
+
+ /* Otherwise neutral will allow any purpose */
+ else
+ neutral = allow;
+
+ /* The value set if a purpose is explictly rejected */
+ disallow = CKT_NSS_NOT_TRUSTED;
+
+ for (i = 0; eku_attribute_map[i].type != CKA_INVALID; i++) {
+ attrs[i].type = eku_attribute_map[i].type;
+ if (dict_rej && p11_dict_get (dict_rej, eku_attribute_map[i].oid)) {
+ attrs[i].pValue = &disallow;
+ attrs[i].ulValueLen = sizeof (disallow);
+ } else if (dict_purp && p11_dict_get (dict_purp, eku_attribute_map[i].oid)) {
+ attrs[i].pValue = &allow;
+ attrs[i].ulValueLen = sizeof (allow);
+ } else {
+ attrs[i].pValue = &neutral;
+ attrs[i].ulValueLen = sizeof (neutral);
+ }
+ }
+
+ p11_dict_free (dict_purp);
+ p11_dict_free (dict_rej);
+
+ return p11_attrs_buildn (object, attrs, i);
+}
+
+static void
+replace_nss_trust_object (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert,
+ CK_BBOOL trust,
+ CK_BBOOL distrust,
+ CK_BBOOL authority,
+ const char **purposes,
+ const char **rejects)
+{
+ CK_ATTRIBUTE *attrs = NULL;
+ CK_TRUST allow;
+ CK_RV rv;
+
+ CK_OBJECT_CLASS klassv = CKO_NSS_TRUST;
+ CK_BYTE sha1v[P11_CHECKSUM_SHA1_LENGTH];
+ CK_BYTE md5v[P11_CHECKSUM_MD5_LENGTH];
+ CK_BBOOL generated = CK_FALSE;
+ CK_BBOOL falsev = CK_FALSE;
+ CK_BBOOL truev = CK_TRUE;
+
+ CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
+ CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &falsev, sizeof (falsev) };
+ CK_ATTRIBUTE autogen = { CKA_X_GENERATED, &truev, sizeof (truev) };
+ CK_ATTRIBUTE invalid = { CKA_INVALID, };
+
+ CK_ATTRIBUTE md5_hash = { CKA_CERT_MD5_HASH, md5v, sizeof (md5v) };
+ CK_ATTRIBUTE sha1_hash = { CKA_CERT_SHA1_HASH, sha1v, sizeof (sha1v) };
+
+ CK_ATTRIBUTE step_up_approved = { CKA_TRUST_STEP_UP_APPROVED, &falsev, sizeof (falsev) };
+
+ CK_ATTRIBUTE_PTR label;
+ CK_ATTRIBUTE_PTR id;
+ CK_ATTRIBUTE_PTR der;
+ CK_ATTRIBUTE_PTR subject;
+ CK_ATTRIBUTE_PTR issuer;
+ CK_ATTRIBUTE_PTR serial_number;
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_CERT_SHA1_HASH, sha1v, sizeof (sha1v) },
+ { CKA_CLASS, &klassv, sizeof (klassv) },
+ { CKA_X_GENERATED, &generated, sizeof (generated) },
+ { CKA_INVALID }
+ };
+
+ /* Setup the hashes of the DER certificate value */
+ der = p11_attrs_find (cert, CKA_VALUE);
+ return_if_fail (der != NULL);
+ p11_checksum_md5 (md5v, der->pValue, der->ulValueLen, NULL);
+ p11_checksum_sha1 (sha1v, der->pValue, der->ulValueLen, NULL);
+
+ /* If there is a non-auto-generated NSS trust object, then step away */
+ generated = CK_FALSE;
+ if (p11_index_find (index, match))
+ return;
+
+ /* Copy all of the following attributes from certificate */
+ id = p11_attrs_find (cert, CKA_ID);
+ return_if_fail (id != NULL);
+ subject = p11_attrs_find (cert, CKA_SUBJECT);
+ if (subject == NULL)
+ subject = &invalid;
+ issuer = p11_attrs_find (cert, CKA_ISSUER);
+ if (issuer == NULL)
+ issuer = &invalid;
+ serial_number = p11_attrs_find (cert, CKA_SERIAL_NUMBER);
+ if (serial_number == NULL)
+ serial_number = &invalid;
+
+ /* Try to use the same label */
+ label = p11_attrs_find (cert, CKA_LABEL);
+ if (label == NULL)
+ label = &invalid;
+
+ attrs = p11_attrs_build (NULL, &klass, &modifiable, id, label,
+ subject, issuer, serial_number, &md5_hash, &sha1_hash,
+ &step_up_approved, &autogen, NULL);
+ return_if_fail (attrs != NULL);
+
+ /* Calculate the default allow trust */
+ if (distrust)
+ allow = CKT_NSS_NOT_TRUSTED;
+ else if (trust && authority)
+ allow = CKT_NSS_TRUSTED_DELEGATOR;
+ else if (trust)
+ allow = CKT_NSS_TRUSTED;
+ else
+ allow = CKT_NSS_TRUST_UNKNOWN;
+
+ attrs = build_trust_object_ku (builder, index, cert, attrs, allow);
+ return_if_fail (attrs != NULL);
+
+ attrs = build_trust_object_eku (attrs, allow, purposes, rejects);
+ return_if_fail (attrs != NULL);
+
+ /* Replace related generated objects with this new one */
+ generated = CK_TRUE;
+ rv = p11_index_replace (index, match, CKA_CERT_MD5_HASH, attrs);
+ return_if_fail (rv == CKR_OK);
+}
+
+static void
+build_assertions (p11_array *array,
+ CK_ATTRIBUTE *cert,
+ CK_X_ASSERTION_TYPE type,
+ const char **oids)
+{
+ CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION;
+ CK_BBOOL truev = CK_TRUE;
+ CK_BBOOL falsev = CK_FALSE;
+
+ CK_ATTRIBUTE klass = { CKA_CLASS, &assertion, sizeof (assertion) };
+ CK_ATTRIBUTE private = { CKA_PRIVATE, &falsev, sizeof (falsev) };
+ CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &falsev, sizeof (falsev) };
+ CK_ATTRIBUTE assertion_type = { CKA_X_ASSERTION_TYPE, &type, sizeof (type) };
+ CK_ATTRIBUTE autogen = { CKA_X_GENERATED, &truev, sizeof (truev) };
+ CK_ATTRIBUTE purpose = { CKA_X_PURPOSE, };
+ CK_ATTRIBUTE invalid = { CKA_INVALID, };
+
+ CK_ATTRIBUTE *issuer;
+ CK_ATTRIBUTE *serial;
+ CK_ATTRIBUTE *value;
+ CK_ATTRIBUTE *label;
+ CK_ATTRIBUTE *id;
+ CK_ATTRIBUTE *attrs;
+ int i;
+
+ label = p11_attrs_find (cert, CKA_LABEL);
+ if (label == NULL)
+ label = &invalid;
+
+ id = p11_attrs_find (cert, CKA_ID);
+ issuer = p11_attrs_find (cert, CKA_ISSUER);
+ serial = p11_attrs_find (cert, CKA_SERIAL_NUMBER);
+ value = p11_attrs_find (cert, CKA_VALUE);
+
+ return_if_fail (id != NULL && issuer != NULL && serial != NULL && value != NULL);
+
+ for (i = 0; oids[i] != NULL; i++) {
+ purpose.pValue = (void *)oids[i];
+ purpose.ulValueLen = strlen (oids[i]);
+
+ attrs = p11_attrs_build (NULL, &klass, &private, &modifiable,
+ id, label, &assertion_type, &purpose,
+ issuer, serial, value, &autogen, NULL);
+ return_if_fail (attrs != NULL);
+
+ if (!p11_array_push (array, attrs))
+ return_if_reached ();
+ }
+}
+
+static void
+build_trust_assertions (p11_array *built,
+ CK_ATTRIBUTE *cert,
+ CK_BBOOL trust,
+ CK_BBOOL distrust,
+ CK_BBOOL authority,
+ const char **purposes,
+ const char **rejects)
+{
+ const char *all_purposes[] = {
+ P11_OID_SERVER_AUTH_STR,
+ P11_OID_CLIENT_AUTH_STR,
+ P11_OID_CODE_SIGNING_STR,
+ P11_OID_EMAIL_PROTECTION_STR,
+ P11_OID_IPSEC_END_SYSTEM_STR,
+ P11_OID_IPSEC_TUNNEL_STR,
+ P11_OID_IPSEC_USER_STR,
+ P11_OID_TIME_STAMPING_STR,
+ NULL,
+ };
+
+ /* Build assertions for anything that's explicitly rejected */
+ if (rejects) {
+ build_assertions (built, cert, CKT_X_DISTRUSTED_CERTIFICATE, rejects);
+ }
+
+ if (distrust) {
+ /*
+ * Trust assertions are defficient in that they don't blacklist a certificate
+ * for any purposes. So we just have to go wild and write out a bunch of
+ * assertions for all our known purposes.
+ */
+ build_assertions (built, cert, CKT_X_DISTRUSTED_CERTIFICATE, all_purposes);
+ }
+
+ /*
+ * TODO: Build pinned certificate assertions. That is, trusted
+ * certificates where not an authority.
+ */
+
+ if (trust && authority) {
+ if (purposes) {
+ /* If purposes explicitly set, then anchor for those purposes */
+ build_assertions (built, cert, CKT_X_ANCHORED_CERTIFICATE, purposes);
+ } else {
+ /* If purposes not-explicitly set, then anchor for all known */
+ build_assertions (built, cert, CKT_X_ANCHORED_CERTIFICATE, all_purposes);
+ }
+ }
+}
+
+static void
+replace_trust_assertions (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert,
+ CK_BBOOL trust,
+ CK_BBOOL distrust,
+ CK_BBOOL authority,
+ const char **purposes,
+ const char **rejects)
+{
+ CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION;
+ CK_BBOOL generated = CK_FALSE;
+ CK_ATTRIBUTE *value;
+ p11_array *built;
+ CK_RV rv;
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_VALUE, },
+ { CKA_CLASS, &assertion, sizeof (assertion) },
+ { CKA_X_GENERATED, &generated, sizeof (generated) },
+ { CKA_INVALID }
+ };
+
+ value = p11_attrs_find (cert, CKA_VALUE);
+ return_if_fail (value != NULL);
+
+ built = p11_array_new (NULL);
+ build_trust_assertions (built, cert, trust, distrust, authority, purposes, rejects);
+
+ generated = CK_TRUE;
+ match[0].pValue = value->pValue;
+ match[0].ulValueLen = value->ulValueLen;
+ rv = p11_index_replace_all (index, match, CKA_X_PURPOSE, built);
+ return_if_fail (rv == CKR_OK);
+
+ p11_array_free (built);
+}
+
+static void
+remove_trust_and_assertions (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *attrs)
+{
+ CK_BBOOL truev = CK_TRUE;
+ CK_ATTRIBUTE *id;
+ p11_array *array;
+ CK_RV rv;
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_ID, },
+ { CKA_X_GENERATED, &truev, sizeof (truev) },
+ { CKA_INVALID }
+ };
+
+ id = p11_attrs_find (attrs, CKA_ID);
+ return_if_fail (id != NULL);
+
+ /* An empty array of replacements */
+ array = p11_array_new (NULL);
+
+ /* Remove all related NSS trust objects */
+ match[0].pValue = id->pValue;
+ match[0].ulValueLen = id->ulValueLen;
+ rv = p11_index_replace_all (index, match, CKA_INVALID, array);
+ return_if_fail (rv == CKR_OK);
+
+ p11_array_free (array);
+}
+
+static void
+replace_trust_and_assertions (p11_builder *builder,
+ p11_index *index,
+ CK_ATTRIBUTE *cert)
+{
+ CK_BBOOL trust = CK_FALSE;
+ CK_BBOOL distrust = CK_FALSE;
+ CK_BBOOL authority = CK_FALSE;
+ p11_array *purposes = NULL;
+ p11_array *rejects = NULL;
+ const char **purposev;
+ const char **rejectv;
+ CK_ULONG category;
+ unsigned char *ext;
+ size_t ext_len;
+
+ /*
+ * We look up all this information in advance, since it's used
+ * by the various adapter objects, and we don't have to parse
+ * it multiple times.
+ */
+
+ if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &trust))
+ trust = CK_FALSE;
+ if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &distrust))
+ distrust = CK_FALSE;
+ if (p11_attrs_find_ulong (cert, CKA_CERTIFICATE_CATEGORY, &category) && category == 2)
+ authority = CK_TRUE;
+
+ if (!distrust) {
+ ext = lookup_extension (builder, index, cert, P11_OID_EXTENDED_KEY_USAGE, &ext_len);
+ if (ext != NULL) {
+ purposes = p11_x509_parse_extended_key_usage (builder->asn1_defs, ext, ext_len);
+ if (purposes == NULL)
+ p11_message ("invalid extended key usage certificate extension");
+ free (ext);
+ }
+
+ ext = lookup_extension (builder, index, cert, P11_OID_OPENSSL_REJECT, &ext_len);
+ if (ext != NULL) {
+ rejects = p11_x509_parse_extended_key_usage (builder->asn1_defs, ext, ext_len);
+ if (rejects == NULL)
+ p11_message ("invalid reject key usage certificate extension");
+ free (ext);
+ }
+ }
+
+ /* null-terminate these arrays and use as strv's */
+ purposev = rejectv = NULL;
+ if (rejects) {
+ if (!p11_array_push (rejects, NULL))
+ return_if_reached ();
+ rejectv = (const char **)rejects->elem;
+ }
+ if (purposes) {
+ if (!p11_array_push (purposes, NULL))
+ return_if_reached ();
+ purposev = (const char **)purposes->elem;
+ }
+
+ replace_nss_trust_object (builder, index, cert, trust, distrust,
+ authority, purposev, rejectv);
+ replace_trust_assertions (builder, index, cert, trust, distrust,
+ authority, purposev, rejectv);
+
+ p11_array_free (purposes);
+ p11_array_free (rejects);
+}
+
+static void
+replace_compat_for_cert (p11_builder *builder,
+ p11_index *index,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *attrs)
+{
+ static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
+ static CK_CERTIFICATE_TYPE x509 = CKC_X_509;
+
+ CK_ATTRIBUTE *value;
+ CK_ATTRIBUTE *id;
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_VALUE, },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID }
+ };
+
+ value = p11_attrs_find (attrs, CKA_VALUE);
+ id = p11_attrs_find (attrs, CKA_ID);
+ if (value == NULL || id == NULL)
+ return;
+
+ /*
+ * If this certificate is going away, then find duplicate. In this
+ * case all the trust assertions are recalculated with this new
+ * certificate in mind.
+ */
+ if (handle == 0) {
+ match[0].pValue = value->pValue;
+ match[0].ulValueLen = value->ulValueLen;
+ handle = p11_index_find (index, match);
+ if (handle != 0)
+ attrs = p11_index_lookup (index, handle);
+ }
+
+ if (handle == 0)
+ remove_trust_and_assertions (builder, index, attrs);
+ else
+ replace_trust_and_assertions (builder, index, attrs);
+}
+
+static void
+replace_compat_for_ext (p11_builder *builder,
+ p11_index *index,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *attrs)
+{
+
+ CK_OBJECT_HANDLE *handles;
+ CK_ATTRIBUTE *id;
+ int i;
+
+ id = p11_attrs_find (attrs, CKA_ID);
+ if (id == NULL)
+ return;
+
+ handles = lookup_related (index, CKO_CERTIFICATE, id);
+ for (i = 0; handles && handles[i] != 0; i++) {
+ attrs = p11_index_lookup (index, handles[i]);
+ replace_trust_and_assertions (builder, index, attrs);
+ }
+ free (handles);
+}
+
+static void
+update_related_category (p11_builder *builder,
+ p11_index *index,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *attrs)
+{
+ CK_OBJECT_HANDLE *handles;
+ CK_ULONG categoryv = 0UL;
+ CK_ATTRIBUTE *update;
+ CK_ATTRIBUTE *cert;
+ CK_ATTRIBUTE *id;
+ CK_RV rv;
+ int i;
+
+ CK_ATTRIBUTE category[] = {
+ { CKA_CERTIFICATE_CATEGORY, &categoryv, sizeof (categoryv) },
+ { CKA_INVALID, },
+ };
+
+ id = p11_attrs_find (attrs, CKA_ID);
+ if (id == NULL)
+ return;
+
+ /* Find all other objects with this handle */
+ handles = lookup_related (index, CKO_CERTIFICATE, id);
+
+ for (i = 0; handles && handles[i] != 0; i++) {
+ cert = p11_index_lookup (index, handle);
+
+ if (calc_certificate_category (builder, index, cert, &categoryv)) {
+ update = p11_attrs_build (NULL, &category, NULL);
+ rv = p11_index_update (index, handles[i], update);
+ return_if_fail (rv == CKR_OK);
+ }
+ }
+
+ free (handles);
+}
+
+void
+p11_builder_changed (void *bilder,
+ p11_index *index,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *attrs)
+{
+ static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
+ static CK_OBJECT_CLASS extension = CKO_X_CERTIFICATE_EXTENSION;
+ static CK_CERTIFICATE_TYPE x509 = CKC_X_509;
+
+ static CK_ATTRIBUTE match_cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_INVALID }
+ };
+
+ static CK_ATTRIBUTE match_eku[] = {
+ { CKA_CLASS, &extension, sizeof (extension) },
+ { CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE,
+ sizeof (P11_OID_EXTENDED_KEY_USAGE) },
+ { CKA_INVALID }
+ };
+
+ static CK_ATTRIBUTE match_ku[] = {
+ { CKA_CLASS, &extension, sizeof (extension) },
+ { CKA_OBJECT_ID, (void *)P11_OID_KEY_USAGE,
+ sizeof (P11_OID_KEY_USAGE) },
+ { CKA_INVALID }
+ };
+
+ static CK_ATTRIBUTE match_bc[] = {
+ { CKA_CLASS, &extension, sizeof (extension) },
+ { CKA_OBJECT_ID, (void *)P11_OID_BASIC_CONSTRAINTS,
+ sizeof (P11_OID_BASIC_CONSTRAINTS) },
+ { CKA_INVALID }
+ };
+
+ p11_builder *builder = bilder;
+
+ return_if_fail (builder != NULL);
+ return_if_fail (index != NULL);
+ return_if_fail (attrs != NULL);
+
+ /*
+ * Treat these operations as loading, not modifying/creating, so we get
+ * around many of the rules that govern object creation
+ */
+ p11_index_batch (index);
+
+ /* A certificate */
+ if (p11_attrs_match (attrs, match_cert)) {
+ replace_compat_for_cert (builder, index, handle, attrs);
+
+ /* An ExtendedKeyUsage extension */
+ } else if (p11_attrs_match (attrs, match_eku) ||
+ p11_attrs_match (attrs, match_ku)) {
+ replace_compat_for_ext (builder, index, handle, attrs);
+
+ /* A BasicConstraints extension */
+ } else if (p11_attrs_match (attrs, match_bc)) {
+ update_related_category (builder, index, handle, attrs);
+ }
+
+ p11_index_finish (index);
+}
diff --git a/trust/adapter.h b/trust/builder.h
index fb4ad4e..c837514 100644
--- a/trust/adapter.h
+++ b/trust/builder.h
@@ -32,13 +32,35 @@
* Author: Stef Walter <stefw@redhat.com>
*/
-#include "array.h"
-#include "parser.h"
+#ifndef P11_BUILDER_H_
+#define P11_BUILDER_H_
-#ifndef P11_ADAPTER_H_
-#define P11_ADAPTER_H_
+#include "asn1.h"
+#include "dict.h"
+#include "index.h"
+#include "pkcs11.h"
-void p11_adapter_build_objects (p11_parser *parser,
- p11_array *parsing);
+enum {
+ P11_BUILDER_FLAG_NONE = 0,
+ P11_BUILDER_FLAG_TOKEN = 1 << 1,
+};
-#endif /* P11_ADAPTER_H_ */
+typedef struct _p11_builder p11_builder;
+
+p11_builder * p11_builder_new (int flags);
+
+void p11_builder_free (p11_builder *builder);
+
+CK_RV p11_builder_build (void *builder,
+ p11_index *index,
+ CK_ATTRIBUTE **attrs,
+ CK_ATTRIBUTE *merge);
+
+void p11_builder_changed (void *builder,
+ p11_index *index,
+ CK_OBJECT_HANDLE handle,
+ CK_ATTRIBUTE *attrs);
+
+p11_asn1_cache * p11_builder_get_cache (p11_builder *builder);
+
+#endif /* P11_BUILDER_H_ */
diff --git a/trust/parser.c b/trust/parser.c
index 0b62f01..978d30e 100644
--- a/trust/parser.c
+++ b/trust/parser.c
@@ -34,7 +34,6 @@
#include "config.h"
-#include "adapter.h"
#include "array.h"
#include "asn1.h"
#include "attrs.h"
@@ -63,359 +62,115 @@
#include <unistd.h>
struct _p11_parser {
+ p11_index *index;
+ p11_asn1_cache *asn1_cache;
p11_dict *asn1_defs;
-
- /* Set during a parse */
- p11_parser_sink sink;
- void *sink_data;
- const char *basename;
+ char *basename;
int flags;
-
- /* Parsing state */
- p11_array *parsing;
- node_asn *cert_asn;
- const unsigned char *cert_der;
- size_t cert_len;
};
+#define ID_LENGTH P11_CHECKSUM_SHA1_LENGTH
+
typedef int (* parser_func) (p11_parser *parser,
const unsigned char *data,
size_t length);
-static void
-begin_parsing (p11_parser *parser,
- node_asn *cert_asn,
- const unsigned char *cert_der,
- size_t cert_len)
+static CK_ATTRIBUTE *
+populate_trust (p11_parser *parser,
+ CK_ATTRIBUTE *attrs)
{
- return_if_fail (parser->parsing == NULL);
- return_if_fail (parser->cert_asn == NULL);
- return_if_fail (parser->cert_der == NULL);
+ CK_BBOOL trustedv;
+ CK_BBOOL distrustv;
- parser->parsing = p11_array_new (NULL);
+ CK_ATTRIBUTE trusted = { CKA_TRUSTED, &trustedv, sizeof (trustedv) };
+ CK_ATTRIBUTE distrust = { CKA_X_DISTRUSTED, &distrustv, sizeof (distrustv) };
/*
- * We make note of these for later looking up certificate
- * extensions. See p11_parsed_find_extension().
+ * If we're are parsing an anchor location, then warn about any ditsrusted
+ * certificates there, but don't go ahead and automatically make them
+ * trusted anchors.
*/
- parser->cert_asn = cert_asn;
- parser->cert_der = cert_der;
- parser->cert_len = cert_len;
-}
+ if (parser->flags & P11_PARSE_FLAG_ANCHOR) {
+ if (p11_attrs_find_bool (attrs, CKA_X_DISTRUSTED, &distrustv) && distrustv) {
+ p11_message ("certificate with distrust in location for anchors: %s", parser->basename);
+ return attrs;
-static void
-finish_parsing (p11_parser *parser,
- node_asn *cert_asn)
-{
- CK_ATTRIBUTE *attrs;
- int i;
+ }
- return_if_fail (parser->parsing != NULL);
+ trustedv = CK_TRUE;
+ distrustv = CK_FALSE;
- /* This is a double check */
- return_if_fail (parser->cert_asn == cert_asn);
+ /*
+ * If we're parsing a blacklist location, then force all certificates to
+ * be blacklisted, regardless of whether they contain anchor information.
+ */
+ } else if (parser->flags & P11_PARSE_FLAG_BLACKLIST) {
+ if (p11_attrs_find_bool (attrs, CKA_TRUSTED, &trustedv) && trustedv)
+ p11_message ("overriding trust for anchor in blacklist: %s", parser->basename);
- /* Update the certificate state */
- p11_parsing_update_certificate (parser, parser->parsing);
+ trustedv = CK_FALSE;
+ distrustv = CK_TRUE;
- /* Call all the hooks for generating further objects */
- p11_adapter_build_objects (parser, parser->parsing);
+ /*
+ * If the location doesn't have a flag, then fill in trust attributes
+ * if they are missing: neither an anchor or blacklist.
+ */
+ } else {
+ trustedv = CK_FALSE;
+ distrustv = CK_FALSE;
- for (i = 0; i < parser->parsing->num; i++) {
- attrs = parser->parsing->elem[i];
- if (parser->sink)
- (parser->sink) (attrs, parser->sink_data);
- else
- p11_attrs_free (attrs);
+ if (p11_attrs_find_valid (attrs, CKA_TRUSTED))
+ trusted.type = CKA_INVALID;
+ if (p11_attrs_find_valid (attrs, CKA_X_DISTRUSTED))
+ distrust.type = CKA_INVALID;
}
- p11_array_free (parser->parsing);
-
- parser->parsing = NULL;
- parser->cert_asn = NULL;
- parser->cert_der = NULL;
- parser->cert_len = 0;
+ return p11_attrs_build (attrs, &trusted, &distrust, NULL);
}
-#define ID_LENGTH P11_CHECKSUM_SHA1_LENGTH
-
static void
-id_generate (p11_parser *parser,
- CK_BYTE *vid)
+sink_object (p11_parser *parser,
+ CK_ATTRIBUTE *attrs)
{
- CK_ULONG val = p11_module_next_id ();
- p11_checksum_sha1 (vid, &val, sizeof (val), NULL);
-}
+ CK_OBJECT_CLASS klass;
+ CK_RV rv;
-static CK_ATTRIBUTE *
-build_object (p11_parser *parser,
- CK_OBJECT_CLASS vclass,
- CK_BYTE *vid,
- const char *vlabel)
-{
- CK_ATTRIBUTE *attrs = NULL;
- CK_BBOOL vtrue = CK_TRUE;
- CK_BBOOL vfalse = CK_FALSE;
-
- CK_ATTRIBUTE klass = { CKA_CLASS, &vclass, sizeof (vclass) };
- CK_ATTRIBUTE token = { CKA_TOKEN, &vtrue, sizeof (vtrue) };
- CK_ATTRIBUTE private = { CKA_PRIVATE, &vfalse, sizeof (vfalse) };
- CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) };
- CK_ATTRIBUTE id = { CKA_ID, vid, ID_LENGTH };
- CK_ATTRIBUTE label = { CKA_LABEL, };
-
- if (!vlabel)
- vlabel = parser->basename;
- if (vlabel) {
- label.pValue = (void *)vlabel;
- label.ulValueLen = strlen (vlabel);
- } else {
- label.type = CKA_INVALID;
+ if (p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) &&
+ klass == CKO_CERTIFICATE) {
+ attrs = populate_trust (parser, attrs);
+ return_if_fail (attrs != NULL);
}
- if (!vid)
- id.type = CKA_INVALID;
-
- return p11_attrs_build (attrs, &klass, &token, &private, &modifiable,
- &id, &label, NULL);
+ rv = p11_index_take (parser->index, attrs, NULL);
+ if (rv != CKR_OK)
+ p11_message ("couldn't load file into objects: %s", parser->basename);
}
static void
-calc_check_value (const unsigned char *data,
- size_t length,
- CK_BYTE *check_value)
-{
- unsigned char checksum[P11_CHECKSUM_SHA1_LENGTH];
- p11_checksum_sha1 (checksum, data, length, NULL);
- memcpy (check_value, checksum, 3);
-}
-
-static bool
-calc_date (node_asn *cert,
- const char *field,
- CK_DATE *date)
-{
- node_asn *choice;
- struct tm when;
- char buf[64];
- time_t timet;
- char *sub;
- int len;
- int ret;
-
- choice = asn1_find_node (cert, field);
- return_val_if_fail (choice != NULL, false);
-
- len = sizeof (buf) - 1;
- ret = asn1_read_value (cert, field, buf, &len);
- return_val_if_fail (ret == ASN1_SUCCESS, false);
-
- sub = strconcat (field, ".", buf, NULL);
-
- if (strcmp (buf, "generalTime") == 0) {
- len = sizeof (buf) - 1;
- ret = asn1_read_value (cert, sub, buf, &len);
- return_val_if_fail (ret == ASN1_SUCCESS, false);
- timet = p11_asn1_parse_general (buf, &when);
- return_val_if_fail (timet >= 0, false);
-
- } else if (strcmp (buf, "utcTime") == 0) {
- len = sizeof (buf) - 1;
- ret = asn1_read_value (cert, sub, buf, &len);
- return_val_if_fail (ret == ASN1_SUCCESS, false);
- timet = p11_asn1_parse_utc (buf, &when);
- return_val_if_fail (timet >= 0, false);
-
- } else {
- return_val_if_reached (false);
- }
-
- free (sub);
-
- assert (sizeof (date->year) == 4);
- snprintf ((char *)buf, 5, "%04d", 1900 + when.tm_year);
- memcpy (date->year, buf, 4);
-
- assert (sizeof (date->month) == 2);
- snprintf ((char *)buf, 3, "%02d", when.tm_mon + 1);
- memcpy (date->month, buf, 2);
-
- assert (sizeof (date->day) == 2);
- snprintf ((char *)buf, 3, "%02d", when.tm_mday);
- memcpy (date->day, buf, 2);
-
- return true;
-}
-
-static bool
-calc_element (node_asn *el,
- const unsigned char *data,
- size_t length,
- const char *field,
- CK_ATTRIBUTE *attr)
-{
- int ret;
- int start, end;
-
- ret = asn1_der_decoding_startEnd (el, data, length, field, &start, &end);
- return_val_if_fail (ret == ASN1_SUCCESS, false);
- return_val_if_fail (end >= start, false);
-
- attr->pValue = (void *)(data + start);
- attr->ulValueLen = (end - start) + 1;
- return true;
-}
-
-static CK_ATTRIBUTE *
-build_x509_certificate (p11_parser *parser,
- CK_BYTE *vid,
- node_asn *cert,
- const unsigned char *data,
- size_t length)
+id_generate (p11_parser *parser,
+ CK_BYTE *vid)
{
- CK_ATTRIBUTE *attrs;
- CK_CERTIFICATE_TYPE vx509 = CKC_X_509;
- CK_BYTE vchecksum[3];
- char *label;
-
- CK_DATE vstart;
- CK_DATE vend;
-
- /* Filled in later */
- CK_ULONG vcategory = 0;
- CK_BBOOL vtrusted = (parser->flags & P11_PARSE_FLAG_ANCHOR) ? CK_TRUE : CK_FALSE;
- CK_BBOOL vdistrusted = (parser->flags & P11_PARSE_FLAG_BLACKLIST) ? CK_TRUE : CK_FALSE;
-
- CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &vx509, sizeof (vx509) };
- CK_ATTRIBUTE certificate_category = { CKA_CERTIFICATE_CATEGORY, &vcategory, sizeof (vcategory) };
- CK_ATTRIBUTE value = { CKA_VALUE, (void *)data, length };
-
- CK_ATTRIBUTE check_value = { CKA_CHECK_VALUE, &vchecksum, sizeof (vchecksum) };
- CK_ATTRIBUTE trusted = { CKA_TRUSTED, &vtrusted, sizeof (vtrusted) };
- CK_ATTRIBUTE distrusted = { CKA_X_DISTRUSTED, &vdistrusted, sizeof (vdistrusted) };
- CK_ATTRIBUTE start_date = { CKA_START_DATE, &vstart, sizeof (vstart) };
- CK_ATTRIBUTE end_date = { CKA_END_DATE, &vend, sizeof (vend) };
- CK_ATTRIBUTE subject = { CKA_SUBJECT, };
- CK_ATTRIBUTE issuer = { CKA_ISSUER, };
- CK_ATTRIBUTE serial_number = { CKA_SERIAL_NUMBER, };
-
- /*
- * The following are not present:
- * CKA_URL
- * CKA_HASH_OF_SUBJECT_PUBLIC_KEY
- * CKA_HASH_OF_ISSUER_PUBLIC_KEY
- * CKA_JAVA_MIDP_SECURITY_DOMAIN
- */
-
- calc_check_value (data, length, vchecksum);
-
- if (!calc_date (cert, "tbsCertificate.validity.notBefore", &vstart))
- start_date.type = CKA_INVALID;
- if (!calc_date (cert, "tbsCertificate.validity.notAfter", &vend))
- end_date.type = CKA_INVALID;
-
- if (!calc_element (cert, data, length, "tbsCertificate.issuer.rdnSequence", &issuer))
- issuer.type = CKA_INVALID;
- if (!calc_element (cert, data, length, "tbsCertificate.subject.rdnSequence", &subject))
- subject.type = CKA_INVALID;
- if (!calc_element (cert, data, length, "tbsCertificate.serialNumber", &serial_number))
- serial_number.type = CKA_INVALID;
-
- label = p11_x509_lookup_dn_name (parser->cert_asn, "tbsCertificate.subject",
- parser->cert_der, parser->cert_len, P11_OID_CN);
- if (!label)
- label = p11_x509_lookup_dn_name (parser->cert_asn, "tbsCertificate.subject",
- parser->cert_der, parser->cert_len, P11_OID_OU);
- if (!label)
- label = p11_x509_lookup_dn_name (parser->cert_asn, "tbsCertificate.subject",
- parser->cert_der, parser->cert_len, P11_OID_O);
-
- attrs = build_object (parser, CKO_CERTIFICATE, vid, label);
- return_val_if_fail (attrs != NULL, NULL);
- free (label);
-
- attrs = p11_attrs_build (attrs, &certificate_type, &certificate_category,
- &check_value, &trusted, &distrusted, &start_date, &end_date,
- &subject, &issuer, &serial_number, &value,
- NULL);
- return_val_if_fail (attrs != NULL, NULL);
-
- if (!p11_array_push (parser->parsing, attrs))
- return_val_if_reached (NULL);
-
- return attrs;
+ CK_ULONG val = p11_module_next_id ();
+ p11_checksum_sha1 (vid, &val, sizeof (val), NULL);
}
static CK_ATTRIBUTE *
-match_parsing_object (p11_parser *parser,
- CK_ATTRIBUTE *match)
-{
- CK_ATTRIBUTE *attrs;
- int i;
-
- for (i = 0; i < parser->parsing->num; i++) {
- attrs = parser->parsing->elem[i];
- if (p11_attrs_match (attrs, match))
- return attrs;
- }
-
- return NULL;
-}
-
-unsigned char *
-p11_parsing_get_extension (p11_parser *parser,
- p11_array *parsing,
- const unsigned char *oid,
- size_t *length)
+certificate_attrs (p11_parser *parser,
+ CK_BYTE *idv,
+ const unsigned char *der,
+ size_t der_len)
{
- CK_OBJECT_CLASS klass = CKO_X_CERTIFICATE_EXTENSION;
- CK_ATTRIBUTE *attrs;
- CK_ATTRIBUTE *attr;
-
- CK_ATTRIBUTE match[] = {
- { CKA_OBJECT_ID, (void *)oid, p11_oid_length (oid) },
- { CKA_CLASS, &klass, sizeof (klass) },
- { CKA_INVALID },
- };
-
- return_val_if_fail (parser != NULL, NULL);
- return_val_if_fail (parser->parsing == parsing, NULL);
- return_val_if_fail (length != NULL, NULL);
- return_val_if_fail (oid != NULL, NULL);
-
- attrs = match_parsing_object (parser, match);
- if (attrs != NULL) {
- attr = p11_attrs_find (attrs, CKA_VALUE);
- return_val_if_fail (attr != NULL, NULL);
-
- *length = attr->ulValueLen;
- return memdup (attr->pValue, attr->ulValueLen);
-
- /* Couldn't find a parsed extension, so look in the current certificate */
- } else if (parser->cert_asn) {
- return p11_x509_find_extension (parser->cert_asn, oid,
- parser->cert_der, parser->cert_len,
- length);
- }
-
- return NULL;
-}
-
-CK_ATTRIBUTE *
-p11_parsing_get_certificate (p11_parser *parser,
- p11_array *parsing)
-{
- CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
-
- CK_ATTRIBUTE match[] = {
- { CKA_CLASS, &klass, sizeof (klass) },
- { CKA_INVALID },
- };
+ CK_OBJECT_CLASS klassv = CKO_CERTIFICATE;
+ CK_CERTIFICATE_TYPE x509 = CKC_X_509;
+ CK_BBOOL modifiablev = CK_FALSE;
- return_val_if_fail (parser != NULL, NULL);
- return_val_if_fail (parser->parsing == parsing, NULL);
+ CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
+ CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
+ CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) };
+ CK_ATTRIBUTE value = { CKA_VALUE, (void *)der, der_len };
+ CK_ATTRIBUTE id = { CKA_ID, idv, ID_LENGTH };
- return match_parsing_object (parser, match);
+ return p11_attrs_build (NULL, &klass, &modifiable, &certificate_type, &value, &id, NULL);
}
static int
@@ -423,81 +178,72 @@ parse_der_x509_certificate (p11_parser *parser,
const unsigned char *data,
size_t length)
{
- CK_BYTE vid[ID_LENGTH];
+ CK_BYTE idv[ID_LENGTH];
CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *value;
node_asn *cert;
cert = p11_asn1_decode (parser->asn1_defs, "PKIX1.Certificate", data, length, NULL);
if (cert == NULL)
return P11_PARSE_UNRECOGNIZED;
- begin_parsing (parser, cert, data, length);
-
/* The CKA_ID links related objects */
- id_generate (parser, vid);
+ id_generate (parser, idv);
- attrs = build_x509_certificate (parser, vid, cert, data, length);
+ attrs = certificate_attrs (parser, idv, data, length);
return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
- finish_parsing (parser, cert);
- asn1_delete_structure (&cert);
+ value = p11_attrs_find (attrs, CKA_VALUE);
+ assert (value != NULL);
+ p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
+ value->pValue, value->ulValueLen);
+
+ sink_object (parser, attrs);
return P11_PARSE_SUCCESS;
}
-static int
-build_der_extension (p11_parser *parser,
- CK_ATTRIBUTE *cert,
- const unsigned char *oid_der,
- CK_BBOOL vcritical,
- const unsigned char *ext_der,
- int ext_len)
+static CK_ATTRIBUTE *
+extension_attrs (p11_parser *parser,
+ CK_BYTE *idv,
+ const unsigned char *oid_der,
+ CK_BBOOL vcritical,
+ const unsigned char *ext_der,
+ int ext_len)
{
+ CK_OBJECT_CLASS klassv = CKO_X_CERTIFICATE_EXTENSION;
+ CK_BBOOL modifiablev = CK_FALSE;
+
+ CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
+ CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) };
CK_ATTRIBUTE critical = { CKA_X_CRITICAL, &vcritical, sizeof (vcritical) };
CK_ATTRIBUTE oid = { CKA_OBJECT_ID, (void *)oid_der, p11_oid_length (oid_der) };
CK_ATTRIBUTE value = { CKA_VALUE, (void *)ext_der, ext_len };
- CK_ATTRIBUTE invalid = { CKA_INVALID, };
-
- CK_ATTRIBUTE *attrs;
- CK_ATTRIBUTE *id;
- CK_ATTRIBUTE *label;
+ CK_ATTRIBUTE id = { CKA_ID, idv, ID_LENGTH };
- attrs = build_object (parser, CKO_X_CERTIFICATE_EXTENSION, NULL, NULL);
- return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
-
- id = p11_attrs_find (cert, CKA_ID);
- if (id == NULL)
- id = &invalid;
- label = p11_attrs_find (cert, CKA_LABEL);
- if (id == NULL)
- label = &invalid;
-
- attrs = p11_attrs_build (attrs, id, label, &oid, &critical, &value, NULL);
- return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
+ if (ext_der == NULL)
+ value.type = CKA_INVALID;
- if (!p11_array_push (parser->parsing, attrs))
- return_val_if_reached (P11_PARSE_FAILURE);
-
- return P11_PARSE_SUCCESS;
+ return p11_attrs_build (NULL, &id, &klass, &modifiable, &oid, &critical, &value, NULL);
}
-static int
-build_stapled_extension (p11_parser *parser,
- CK_ATTRIBUTE *cert,
- const unsigned char *oid,
- CK_BBOOL critical,
- node_asn *ext)
+static CK_ATTRIBUTE *
+stapled_attrs (p11_parser *parser,
+ CK_BYTE *idv,
+ const unsigned char *oid,
+ CK_BBOOL critical,
+ node_asn *ext)
{
+ CK_ATTRIBUTE *attrs;
unsigned char *der;
size_t len;
- int ret;
- der = p11_asn1_encode (ext, &len);
- return_val_if_fail (der != NULL, P11_PARSE_FAILURE);
+ attrs = extension_attrs (parser, idv, oid, critical, NULL, 0);
+ return_val_if_fail (attrs != NULL, NULL);
- ret = build_der_extension (parser, cert, oid, critical, (unsigned char *)der, len);
- free (der);
+ der = p11_asn1_encode (ext, &len);
+ return_val_if_fail (der != NULL, NULL);
- return ret;
+ return p11_attrs_take (attrs, CKA_VALUE, der, len);
}
static p11_dict *
@@ -537,13 +283,14 @@ load_seq_of_oid_str (node_asn *node,
return oids;
}
-static int
-build_eku_extension (p11_parser *parser,
- CK_ATTRIBUTE *cert,
- const unsigned char *oid,
- CK_BBOOL critical,
- p11_dict *oid_strs)
+static CK_ATTRIBUTE *
+stapled_eku_attrs (p11_parser *parser,
+ CK_BYTE *idv,
+ const unsigned char *oid,
+ CK_BBOOL critical,
+ p11_dict *oid_strs)
{
+ CK_ATTRIBUTE *attrs;
p11_dictiter iter;
node_asn *dest;
int count = 0;
@@ -551,15 +298,15 @@ build_eku_extension (p11_parser *parser,
int ret;
dest = p11_asn1_create (parser->asn1_defs, "PKIX1.ExtKeyUsageSyntax");
- return_val_if_fail (dest != NULL, P11_PARSE_FAILURE);
+ return_val_if_fail (dest != NULL, NULL);
p11_dict_iterate (oid_strs, &iter);
while (p11_dict_next (&iter, NULL, &value)) {
ret = asn1_write_value (dest, "", "NEW", 1);
- return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
ret = asn1_write_value (dest, "?LAST", value, -1);
- return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
count++;
}
@@ -579,210 +326,40 @@ build_eku_extension (p11_parser *parser,
if (count == 0) {
ret = asn1_write_value (dest, "", "NEW", 1);
- return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
ret = asn1_write_value (dest, "?LAST", P11_OID_RESERVED_PURPOSE_STR, -1);
- return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
+ return_val_if_fail (ret == ASN1_SUCCESS, NULL);
}
- ret = build_stapled_extension (parser, cert, oid, critical, dest);
+ attrs = stapled_attrs (parser, idv, oid, critical, dest);
asn1_delete_structure (&dest);
- return ret;
-}
-
-static int
-build_bc_extension (p11_parser *parser,
- CK_ATTRIBUTE *cert,
- CK_BBOOL critical,
- int is_ca)
-{
- node_asn *ext;
- int ret;
-
- ext = p11_asn1_create (parser->asn1_defs, "PKIX1.BasicConstraints");
- return_val_if_fail (ext != NULL, P11_PARSE_FAILURE);
-
- /* FALSE is the default, so clear if not CA */
- ret = asn1_write_value (ext, "cA", is_ca ? "TRUE" : NULL, is_ca ? -1 : 0);
- return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
-
- /* Clear this optional value */
- ret = asn1_write_value (ext, "pathLenConstraint", NULL, 0);
- return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
-
- ret = build_stapled_extension (parser, cert, P11_OID_BASIC_CONSTRAINTS, critical, ext);
- asn1_delete_structure (&ext);
-
- return ret;
-}
-
-static bool
-is_v1_x509_authority (CK_ATTRIBUTE *cert,
- node_asn *node)
-{
- CK_ATTRIBUTE *subject;
- CK_ATTRIBUTE *issuer;
- char buffer[16];
- int len;
- int ret;
-
- len = sizeof (buffer);
- ret = asn1_read_value (node, "tbsCertificate.version", buffer, &len);
-
- /* The default value */
- if (ret == ASN1_ELEMENT_NOT_FOUND) {
- ret = ASN1_SUCCESS;
- buffer[0] = 0;
- len = 1;
- }
-
- return_val_if_fail (ret == ASN1_SUCCESS, false);
-
- /*
- * In X.509 version v1 is the integer zero. Two's complement
- * integer, but zero is easy to read.
- */
- if (len != 1 || buffer[0] != 0)
- return false;
-
- /* Must be self-signed, ie: same subject and issuer */
- subject = p11_attrs_find (cert, CKA_SUBJECT);
- issuer = p11_attrs_find (cert, CKA_ISSUER);
- return (subject != NULL && issuer != NULL &&
- p11_attr_match_value (subject, issuer->pValue, issuer->ulValueLen));
-}
-
-static void
-update_category (p11_parser *parser,
- CK_ATTRIBUTE *cert)
-{
- CK_ATTRIBUTE *category;
- bool is_ca = 0;
- unsigned char *data;
- size_t length;
- int ret;
-
- /* See if we have a basic constraints extension */
- data = p11_parsing_get_extension (parser, parser->parsing, P11_OID_BASIC_CONSTRAINTS, &length);
- if (data) {
- if (!p11_x509_parse_basic_constraints (parser->asn1_defs, data, length, &is_ca))
- p11_message ("invalid basic constraints certificate extension");
- free (data);
-
- } else if (is_v1_x509_authority (cert, parser->cert_asn)) {
- /*
- * If there is no basic constraints extension, and the CA version is
- * v1, and is self-signed, then we assume this is a certificate authority.
- * So we add a BasicConstraints stapled certificate extension
- */
- is_ca = 1;
- ret = build_bc_extension (parser, cert, CK_FALSE, is_ca);
- return_if_fail (ret == P11_PARSE_SUCCESS);
- }
-
- category = p11_attrs_find (cert, CKA_CERTIFICATE_CATEGORY);
- assert (category != NULL);
- assert (category->pValue != NULL);
- assert (category->ulValueLen == sizeof (CK_ULONG));
-
- /*
- * In the PKCS#11 spec:
- * 0 = unspecified (default value)
- * 1 = token user
- * 2 = authority
- * 3 = other entity
- */
- *((CK_ULONG *)category->pValue) = is_ca ? 2 : 3;
-}
-
-static void
-update_trust_and_distrust (p11_parser *parser,
- CK_ATTRIBUTE *cert)
-{
- CK_ATTRIBUTE *attr;
- CK_BBOOL trusted;
- CK_BBOOL distrusted;
- unsigned char *data;
- size_t length;
- p11_array *ekus;
-
- /*
- * This function is called to update the CKA_TRUSTED and CKA_X_DISTRUSTED
- * fields (anchor and blacklist). Some other code may have updated the
- * related extensions, so this may be called more than once.
- *
- * Since some input like OpenSSL model blacklists as anchors with all
- * purposes being removed/rejected, we account for that here. If there
- * is an ExtendedKeyUsage without any useful purposes, then treat
- * like a blacklist.
- *
- * The certificate is an anchor if the parser is in anchor mode.
- */
-
- trusted = (parser->flags & P11_PARSE_FLAG_ANCHOR) ? CK_TRUE : CK_FALSE;
- distrusted = (parser->flags & P11_PARSE_FLAG_BLACKLIST) ? CK_TRUE : CK_FALSE;
-
- data = p11_parsing_get_extension (parser, parser->parsing, P11_OID_EXTENDED_KEY_USAGE, &length);
- if (data) {
- ekus = p11_x509_parse_extended_key_usage (parser->asn1_defs, data, length);
- if (ekus == NULL)
- p11_message ("invalid extendend key usage certificate extension");
- else if (ekus->num == 0) {
- distrusted = CK_TRUE;
- trusted = CK_FALSE;
- }
-
- p11_array_free (ekus);
- free (data);
- }
-
- attr = p11_attrs_find (cert, CKA_TRUSTED);
- assert (attr != NULL);
- assert (attr->pValue != NULL);
- assert (attr->ulValueLen == sizeof (CK_BBOOL));
- *((CK_BBOOL *)attr->pValue) = trusted;
-
- attr = p11_attrs_find (cert, CKA_X_DISTRUSTED);
- assert (attr != NULL);
- assert (attr->pValue != NULL);
- assert (attr->ulValueLen == sizeof (CK_BBOOL));
- *((CK_BBOOL *)attr->pValue) = distrusted;
-}
-
-void
-p11_parsing_update_certificate (p11_parser *parser,
- p11_array *parsing)
-{
- CK_ATTRIBUTE *cert;
-
- /* Find the certificate to update */
- cert = p11_parsing_get_certificate (parser, parsing);
- if (cert == NULL)
- return;
-
- /* This should match the above cert */
- assert (parser->cert_asn != NULL);
-
- update_category (parser, cert);
- update_trust_and_distrust (parser, cert);
+ return attrs;
}
-
-static int
+static CK_ATTRIBUTE *
build_openssl_extensions (p11_parser *parser,
CK_ATTRIBUTE *cert,
+ CK_BYTE *idv,
node_asn *aux,
const unsigned char *aux_der,
size_t aux_len)
{
+ CK_BBOOL trusted = CK_FALSE;
+ CK_BBOOL distrust = CK_FALSE;
+
+ CK_ATTRIBUTE trust_attrs[] = {
+ { CKA_TRUSTED, &trusted, sizeof (trusted) },
+ { CKA_X_DISTRUSTED, &distrust, sizeof (distrust) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
p11_dict *trust = NULL;
p11_dict *reject = NULL;
p11_dictiter iter;
- CK_ATTRIBUTE *attr;
- CK_BBOOL trusted;
- CK_BBOOL distrust;
void *key;
int start;
int end;
@@ -800,7 +377,7 @@ build_openssl_extensions (p11_parser *parser,
trust = load_seq_of_oid_str (aux, "trust");
ret = asn1_number_of_elements (aux, "reject", &num);
- return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, P11_PARSE_FAILURE);
+ return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
if (ret == ASN1_SUCCESS)
reject = load_seq_of_oid_str (aux, "reject");
@@ -818,8 +395,9 @@ build_openssl_extensions (p11_parser *parser,
*/
if (trust) {
- ret = build_eku_extension (parser, cert, P11_OID_EXTENDED_KEY_USAGE, CK_TRUE, trust);
- return_val_if_fail (ret == P11_PARSE_SUCCESS, ret);
+ attrs = stapled_eku_attrs (parser, idv, P11_OID_EXTENDED_KEY_USAGE, CK_TRUE, trust);
+ return_val_if_fail (attrs != NULL, NULL);
+ sink_object (parser, attrs);
}
/*
@@ -831,49 +409,37 @@ build_openssl_extensions (p11_parser *parser,
*/
if (reject && p11_dict_size (reject) > 0) {
- ret = build_eku_extension (parser, cert, P11_OID_OPENSSL_REJECT, CK_FALSE, reject);
- return_val_if_fail (ret == P11_PARSE_SUCCESS, ret);
+ attrs = stapled_eku_attrs (parser, idv, P11_OID_OPENSSL_REJECT, CK_FALSE, reject);
+ return_val_if_fail (attrs != NULL, NULL);
+ sink_object (parser, attrs);
}
/*
- * If loading from an blacklist flagged directory, then override all
- * trust assumptionsinformation and mark this as a blacklisted certificate
- */
-
- if (parser->flags & P11_PARSE_FLAG_BLACKLIST) {
- trusted = CK_FALSE;
- distrust = CK_TRUE;
-
- /*
* OpenSSL model blacklists as anchors with all purposes being removed/rejected,
* we account for that here. If there is an ExtendedKeyUsage without any
* useful purposes, then treat like a blacklist.
*/
- } else if (trust && p11_dict_size (trust) == 0) {
+ if (trust && p11_dict_size (trust) == 0) {
trusted = CK_FALSE;
distrust = CK_TRUE;
/*
* Otherwise a 'TRUSTED CERTIFICATE' in an input directory is enough to
- * mark this as a trusted certificate, even if we're not explicitly
- * parsing an directory with the anchors flag.
+ * mark this as a trusted certificate.
*/
- } else {
+ } else if (p11_dict_size (trust) > 0) {
trusted = CK_TRUE;
distrust = CK_FALSE;
}
- attr = p11_attrs_find (cert, CKA_TRUSTED);
- assert (attr != NULL);
- assert (attr->pValue != NULL);
- assert (attr->ulValueLen == sizeof (CK_BBOOL));
- *((CK_BBOOL *)attr->pValue) = trusted;
+ /*
+ * OpenSSL model blacklists as anchors with all purposes being removed/rejected,
+ * we account for that here. If there is an ExtendedKeyUsage without any
+ * useful purposes, then treat like a blacklist.
+ */
- attr = p11_attrs_find (cert, CKA_X_DISTRUSTED);
- assert (attr != NULL);
- assert (attr->pValue != NULL);
- assert (attr->ulValueLen == sizeof (CK_BBOOL));
- *((CK_BBOOL *)attr->pValue) = distrust;
+ cert = p11_attrs_merge (cert, p11_attrs_dup (trust_attrs), true);
+ return_val_if_fail (cert != NULL, NULL);
p11_dict_free (trust);
p11_dict_free (reject);
@@ -886,16 +452,17 @@ build_openssl_extensions (p11_parser *parser,
*/
ret = asn1_der_decoding_startEnd (aux, aux_der, aux_len, "keyid", &start, &end);
- return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, P11_PARSE_FAILURE);
+ return_val_if_fail (ret == ASN1_SUCCESS || ret == ASN1_ELEMENT_NOT_FOUND, NULL);
if (ret == ASN1_SUCCESS) {
- ret = build_der_extension (parser, cert, P11_OID_SUBJECT_KEY_IDENTIFIER, CK_FALSE,
- aux_der + start, (end - start) + 1);
- return_val_if_fail (ret == P11_PARSE_SUCCESS, ret);
+ attrs = extension_attrs (parser, idv, P11_OID_SUBJECT_KEY_IDENTIFIER, CK_FALSE,
+ aux_der + start, (end - start) + 1);
+ return_val_if_fail (attrs != NULL, NULL);
+ sink_object (parser, attrs);
}
- return P11_PARSE_SUCCESS;
+ return cert;
}
static int
@@ -904,8 +471,8 @@ parse_openssl_trusted_certificate (p11_parser *parser,
size_t length)
{
CK_ATTRIBUTE *attrs;
- CK_BYTE vid[ID_LENGTH];
- CK_ATTRIBUTE *attr;
+ CK_BYTE idv[ID_LENGTH];
+ CK_ATTRIBUTE *value;
char *label = NULL;
node_asn *cert;
node_asn *aux;
@@ -934,14 +501,18 @@ parse_openssl_trusted_certificate (p11_parser *parser,
return P11_PARSE_UNRECOGNIZED;
}
- begin_parsing (parser, cert, data, cert_len);
-
/* The CKA_ID links related objects */
- id_generate (parser, vid);
+ id_generate (parser, idv);
- attrs = build_x509_certificate (parser, vid, cert, data, cert_len);
+ attrs = certificate_attrs (parser, idv, data, cert_len);
return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
+ /* Cache the parsed certificate ASN.1 for later use by the builder */
+ value = p11_attrs_find (attrs, CKA_VALUE);
+ assert (value != NULL);
+ p11_asn1_cache_take (parser->asn1_cache, cert, "PKIX1.Certificate",
+ value->pValue, value->ulValueLen);
+
/* Pull the label out of the CertAux */
len = 0;
ret = asn1_read_value (aux, "alias", NULL, &len);
@@ -951,20 +522,15 @@ parse_openssl_trusted_certificate (p11_parser *parser,
return_val_if_fail (label != NULL, P11_PARSE_FAILURE);
ret = asn1_read_value (aux, "alias", label, &len);
return_val_if_fail (ret == ASN1_SUCCESS, P11_PARSE_FAILURE);
-
- attr = p11_attrs_find (attrs, CKA_LABEL);
- assert (attr != NULL);
- free (attr->pValue);
- attr->pValue = label;
- attr->ulValueLen = strlen (label);
+ attrs = p11_attrs_take (attrs, CKA_LABEL, label, strlen (label));
+ return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
}
- ret = build_openssl_extensions (parser, attrs, aux, data + cert_len, length - cert_len);
- return_val_if_fail (ret == P11_PARSE_SUCCESS, ret);
-
- finish_parsing (parser, cert);
+ attrs = build_openssl_extensions (parser, attrs, idv, aux,
+ data + cert_len, length - cert_len);
+ return_val_if_fail (attrs != NULL, P11_PARSE_FAILURE);
- asn1_delete_structure (&cert);
+ sink_object (parser, attrs);
asn1_delete_structure (&aux);
return P11_PARSE_SUCCESS;
@@ -979,6 +545,8 @@ on_pem_block (const char *type,
p11_parser *parser = user_data;
int ret;
+ p11_index_batch (parser->index);
+
if (strcmp (type, "CERTIFICATE") == 0) {
ret = parse_der_x509_certificate (parser, contents, length);
@@ -990,6 +558,8 @@ on_pem_block (const char *type,
ret = P11_PARSE_SUCCESS;
}
+ p11_index_finish (parser->index);
+
if (ret != P11_PARSE_SUCCESS)
p11_message ("Couldn't parse PEM block of type %s", type);
}
@@ -1016,12 +586,17 @@ static parser_func all_parsers[] = {
};
p11_parser *
-p11_parser_new (void)
+p11_parser_new (p11_index *index,
+ p11_asn1_cache *asn1_cache)
{
p11_parser parser = { 0, };
- parser.asn1_defs = p11_asn1_defs_load ();
- return_val_if_fail (parser.asn1_defs != NULL, NULL);
+ return_val_if_fail (index != NULL, NULL);
+ return_val_if_fail (asn1_cache != NULL, NULL);
+
+ parser.index = index;
+ parser.asn1_defs = p11_asn1_cache_defs (asn1_cache);
+ parser.asn1_cache = asn1_cache;
return memdup (&parser, sizeof (parser));
}
@@ -1029,10 +604,6 @@ p11_parser_new (void)
void
p11_parser_free (p11_parser *parser)
{
- if (!parser)
- return;
-
- p11_dict_free (parser->asn1_defs);
free (parser);
}
@@ -1041,38 +612,29 @@ p11_parse_memory (p11_parser *parser,
const char *filename,
int flags,
const unsigned char *data,
- size_t length,
- p11_parser_sink sink,
- void *sink_data)
+ size_t length)
{
int ret = P11_PARSE_UNRECOGNIZED;
char *base;
int i;
return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
- return_val_if_fail (parser->sink == NULL, P11_PARSE_FAILURE);
base = basename (filename);
parser->basename = base;
- parser->sink = sink;
- parser->sink_data = sink_data;
parser->flags = flags;
- /* Expected that state is cleaned via finish_parsing () */
- parser->parsing = NULL;
- parser->cert_asn = NULL;
- parser->cert_der = NULL;
- parser->cert_len = 0;
-
for (i = 0; all_parsers[i] != NULL; i++) {
+ p11_index_batch (parser->index);
ret = (all_parsers[i]) (parser, data, length);
+ p11_index_finish (parser->index);
+
if (ret != P11_PARSE_UNRECOGNIZED)
break;
}
+ p11_asn1_cache_flush (parser->asn1_cache);
parser->basename = NULL;
- parser->sink = NULL;
- parser->sink_data = NULL;
parser->flags = 0;
return ret;
@@ -1081,30 +643,24 @@ p11_parse_memory (p11_parser *parser,
int
p11_parse_file (p11_parser *parser,
const char *filename,
- int flags,
- p11_parser_sink sink,
- void *sink_data)
+ int flags)
{
p11_mmap *map;
void *data;
size_t size;
int ret;
+ return_val_if_fail (parser != NULL, P11_PARSE_FAILURE);
+ return_val_if_fail (filename != NULL, P11_PARSE_FAILURE);
+
map = p11_mmap_open (filename, &data, &size);
if (map == NULL) {
p11_message ("couldn't open and map file: %s: %s", filename, strerror (errno));
return P11_PARSE_FAILURE;
}
- ret = p11_parse_memory (parser, filename, flags, data, size, sink, sink_data);
+ ret = p11_parse_memory (parser, filename, flags, data, size);
p11_mmap_close (map);
return ret;
}
-
-p11_dict *
-p11_parser_get_asn1_defs (p11_parser *parser)
-{
- return_val_if_fail (parser != NULL, NULL);
- return parser->asn1_defs;
-}
diff --git a/trust/parser.h b/trust/parser.h
index 201c2c3..ca41d26 100644
--- a/trust/parser.h
+++ b/trust/parser.h
@@ -32,63 +32,42 @@
* Author: Stef Walter <stefw@redhat.com>
*/
+#include "asn1.h"
#include "array.h"
#include "dict.h"
+#include "index.h"
#include "pkcs11.h"
#ifndef P11_PARSER_H_
#define P11_PARSER_H_
enum {
- P11_PARSE_FAILURE = -1,
- P11_PARSE_UNRECOGNIZED = 0,
- P11_PARSE_SUCCESS = 1,
-};
-
-enum {
P11_PARSE_FLAG_NONE = 0,
P11_PARSE_FLAG_ANCHOR = 1 << 0,
- P11_PARSE_FLAG_BLACKLIST = 1 << 1
+ P11_PARSE_FLAG_BLACKLIST = 1 << 1,
};
-#define P11_PARSER_FIRST_HANDLE 0xA0000000UL
+enum {
+ P11_PARSE_FAILURE = -1,
+ P11_PARSE_UNRECOGNIZED = 0,
+ P11_PARSE_SUCCESS = 1,
+};
typedef struct _p11_parser p11_parser;
-p11_parser * p11_parser_new (void);
+p11_parser * p11_parser_new (p11_index *index,
+ p11_asn1_cache *asn1_cache);
void p11_parser_free (p11_parser *parser);
-typedef void (* p11_parser_sink) (CK_ATTRIBUTE *attrs,
- void *user_data);
-
int p11_parse_memory (p11_parser *parser,
const char *filename,
int flags,
const unsigned char *data,
- size_t length,
- p11_parser_sink sink,
- void *sink_data);
+ size_t length);
int p11_parse_file (p11_parser *parser,
const char *filename,
- int flags,
- p11_parser_sink sink,
- void *sink_data);
-
-p11_dict * p11_parser_get_asn1_defs (p11_parser *parser);
-
-/* Functions used for retrieving parsing information */
-
-CK_ATTRIBUTE * p11_parsing_get_certificate (p11_parser *parser,
- p11_array *parsing);
-
-unsigned char * p11_parsing_get_extension (p11_parser *parser,
- p11_array *parsing,
- const unsigned char *oid,
- size_t *length);
-
-void p11_parsing_update_certificate (p11_parser *parser,
- p11_array *parsing);
+ int flags);
#endif
diff --git a/trust/session.c b/trust/session.c
index 30928ed..19434ff 100644
--- a/trust/session.c
+++ b/trust/session.c
@@ -58,7 +58,12 @@ p11_session_new (p11_token *token)
session->handle = p11_module_next_id ();
- session->index = p11_index_new (NULL, NULL, NULL);
+ session->builder = p11_builder_new (P11_BUILDER_FLAG_NONE);
+ return_val_if_fail (session->builder, NULL);
+
+ session->index = p11_index_new (p11_builder_build,
+ p11_builder_changed,
+ session->builder);
return_val_if_fail (session->index != NULL, NULL);
session->token = token;
diff --git a/trust/session.h b/trust/session.h
index c2626d0..b820770 100644
--- a/trust/session.h
+++ b/trust/session.h
@@ -32,6 +32,7 @@
* Author: Stef Walter <stefw@redhat.com>
*/
+#include "builder.h"
#include "index.h"
#include "pkcs11.h"
#include "token.h"
@@ -44,6 +45,7 @@ typedef void (* p11_session_cleanup) (void *data);
typedef struct {
CK_SESSION_HANDLE handle;
p11_index *index;
+ p11_builder *builder;
p11_token *token;
CK_BBOOL loaded;
diff --git a/trust/tests/Makefile.am b/trust/tests/Makefile.am
index cdab991..a675a56 100644
--- a/trust/tests/Makefile.am
+++ b/trust/tests/Makefile.am
@@ -28,6 +28,7 @@ LDADD = \
CHECK_PROGS = \
test-parser \
test-index \
+ test-builder \
test-token \
test-module \
$(NULL)
diff --git a/trust/tests/test-builder.c b/trust/tests/test-builder.c
new file mode 100644
index 0000000..8ffab88
--- /dev/null
+++ b/trust/tests/test-builder.c
@@ -0,0 +1,1611 @@
+/*
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@gnome.org>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "attrs.h"
+#include "builder.h"
+#include "checksum.h"
+#include "debug.h"
+#include "index.h"
+#include "library.h"
+#include "oid.h"
+#include "pkcs11x.h"
+
+#include "test-data.h"
+
+struct {
+ p11_builder *builder;
+ p11_index *index;
+} test;
+
+static CK_TRUST trusted = CKT_NSS_TRUSTED;
+static CK_TRUST trusted_delegator = CKT_NSS_TRUSTED_DELEGATOR;
+static CK_TRUST not_trusted = CKT_NSS_NOT_TRUSTED;
+static CK_TRUST trust_unknown = CKT_NSS_TRUST_UNKNOWN;
+static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
+static CK_OBJECT_CLASS data = CKO_DATA;
+static CK_OBJECT_CLASS certificate_extension = CKO_X_CERTIFICATE_EXTENSION;
+static CK_OBJECT_CLASS nss_trust = CKO_NSS_TRUST;
+static CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION;
+static CK_X_ASSERTION_TYPE anchored_certificate = CKT_X_ANCHORED_CERTIFICATE;
+static CK_X_ASSERTION_TYPE distrusted_certificate = CKT_X_DISTRUSTED_CERTIFICATE;
+static CK_CERTIFICATE_TYPE x509 = CKC_X_509;
+static CK_ULONG certificate_authority = 2;
+static CK_ULONG other_entity = 3;
+static CK_BBOOL truev = CK_TRUE;
+static CK_BBOOL falsev = CK_FALSE;
+
+static void
+setup (CuTest *cu)
+{
+ test.builder = p11_builder_new (P11_BUILDER_FLAG_TOKEN);
+ CuAssertPtrNotNull (cu, test.builder);
+
+ test.index = p11_index_new (p11_builder_build, p11_builder_changed, test.builder);
+ CuAssertPtrNotNull (cu, test.index);
+}
+
+static void
+teardown (CuTest *cu)
+{
+ p11_builder_free (test.builder);
+ p11_index_free (test.index);
+ memset (&test, 0, sizeof (test));
+}
+
+static void
+test_get_cache (CuTest *cu)
+{
+ p11_asn1_cache *cache;
+
+ setup (cu);
+
+ cache = p11_builder_get_cache (test.builder);
+ CuAssertPtrEquals (cu, NULL, p11_asn1_cache_get (cache, "blah", (unsigned char *)"blah", 4));
+
+ teardown (cu);
+}
+
+static void
+test_build_data (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE check[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_TOKEN, &truev, sizeof (truev) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_PRIVATE, &falsev, sizeof (falsev) },
+ { CKA_LABEL, "", 0 },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_APPLICATION, "", 0 },
+ { CKA_OBJECT_ID, "", 0 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *merge;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ merge = p11_attrs_dup (input);
+ rv = p11_builder_build (test.builder, test.index, &attrs, merge);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, check, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_build_certificate (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_LABEL, "the label", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *merge;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ merge = p11_attrs_dup (input);
+ rv = p11_builder_build (test.builder, test.index, &attrs, merge);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_cacert3_ca (cu, attrs, "the label");
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_build_certificate_empty (CuTest *cu)
+{
+ unsigned char checksum[P11_CHECKSUM_SHA1_LENGTH];
+ CK_ULONG domain = 0;
+ CK_ULONG category = 0;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_URL, "http://blah", 11 },
+ { CKA_HASH_OF_ISSUER_PUBLIC_KEY, checksum, sizeof (checksum) },
+ { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, checksum, sizeof (checksum) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_LABEL, "the label", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) },
+ { CKA_VALUE, "", 0 },
+ { CKA_START_DATE, "", 0 },
+ { CKA_END_DATE, "", 0, },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_ISSUER, "", 0 },
+ { CKA_SERIAL_NUMBER, "", 0 },
+ { CKA_HASH_OF_ISSUER_PUBLIC_KEY, checksum, sizeof (checksum) },
+ { CKA_HASH_OF_SUBJECT_PUBLIC_KEY, checksum, sizeof (checksum) },
+ { CKA_LABEL, "the label", 9 },
+ { CKA_JAVA_MIDP_SECURITY_DOMAIN, &domain, sizeof (domain) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *merge;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_checksum_sha1 (checksum, test_cacert3_ca_der, sizeof (test_cacert3_ca_der), NULL);
+
+ attrs = NULL;
+ merge = p11_attrs_dup (input);
+ rv = p11_builder_build (test.builder, test.index, &attrs, merge);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, expected, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static const unsigned char entrust_pretend_ca[] = {
+ 0x30, 0x82, 0x04, 0x5c, 0x30, 0x82, 0x03, 0x44, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x38,
+ 0x63, 0xb9, 0x66, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x81, 0xb4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b,
+ 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x31, 0x40, 0x30, 0x3e, 0x06,
+ 0x03, 0x55, 0x04, 0x0b, 0x14, 0x37, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73,
+ 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x43, 0x50, 0x53, 0x5f, 0x32, 0x30, 0x34, 0x38, 0x20, 0x69,
+ 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x2e, 0x20, 0x28,
+ 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x20, 0x6c, 0x69, 0x61, 0x62, 0x2e, 0x29, 0x31, 0x25, 0x30,
+ 0x23, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1c, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x39,
+ 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x20, 0x4c, 0x69, 0x6d,
+ 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2a, 0x45,
+ 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
+ 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+ 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, 0x34, 0x38, 0x29, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x31,
+ 0x32, 0x32, 0x34, 0x31, 0x37, 0x35, 0x30, 0x35, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32,
+ 0x32, 0x34, 0x31, 0x38, 0x32, 0x30, 0x35, 0x31, 0x5a, 0x30, 0x81, 0xb4, 0x31, 0x14, 0x30, 0x12,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0b, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e,
+ 0x65, 0x74, 0x31, 0x40, 0x30, 0x3e, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x14, 0x37, 0x77, 0x77, 0x77,
+ 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x43, 0x50, 0x53,
+ 0x5f, 0x32, 0x30, 0x34, 0x38, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x20, 0x62, 0x79,
+ 0x20, 0x72, 0x65, 0x66, 0x2e, 0x20, 0x28, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x73, 0x20, 0x6c, 0x69,
+ 0x61, 0x62, 0x2e, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1c, 0x28,
+ 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e,
+ 0x6e, 0x65, 0x74, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33, 0x30, 0x31, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x2a, 0x45, 0x6e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x6e, 0x65,
+ 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30, 0x34, 0x38, 0x29,
+ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
+ 0x00, 0xad, 0x4d, 0x4b, 0xa9, 0x12, 0x86, 0xb2, 0xea, 0xa3, 0x20, 0x07, 0x15, 0x16, 0x64, 0x2a,
+ 0x2b, 0x4b, 0xd1, 0xbf, 0x0b, 0x4a, 0x4d, 0x8e, 0xed, 0x80, 0x76, 0xa5, 0x67, 0xb7, 0x78, 0x40,
+ 0xc0, 0x73, 0x42, 0xc8, 0x68, 0xc0, 0xdb, 0x53, 0x2b, 0xdd, 0x5e, 0xb8, 0x76, 0x98, 0x35, 0x93,
+ 0x8b, 0x1a, 0x9d, 0x7c, 0x13, 0x3a, 0x0e, 0x1f, 0x5b, 0xb7, 0x1e, 0xcf, 0xe5, 0x24, 0x14, 0x1e,
+ 0xb1, 0x81, 0xa9, 0x8d, 0x7d, 0xb8, 0xcc, 0x6b, 0x4b, 0x03, 0xf1, 0x02, 0x0c, 0xdc, 0xab, 0xa5,
+ 0x40, 0x24, 0x00, 0x7f, 0x74, 0x94, 0xa1, 0x9d, 0x08, 0x29, 0xb3, 0x88, 0x0b, 0xf5, 0x87, 0x77,
+ 0x9d, 0x55, 0xcd, 0xe4, 0xc3, 0x7e, 0xd7, 0x6a, 0x64, 0xab, 0x85, 0x14, 0x86, 0x95, 0x5b, 0x97,
+ 0x32, 0x50, 0x6f, 0x3d, 0xc8, 0xba, 0x66, 0x0c, 0xe3, 0xfc, 0xbd, 0xb8, 0x49, 0xc1, 0x76, 0x89,
+ 0x49, 0x19, 0xfd, 0xc0, 0xa8, 0xbd, 0x89, 0xa3, 0x67, 0x2f, 0xc6, 0x9f, 0xbc, 0x71, 0x19, 0x60,
+ 0xb8, 0x2d, 0xe9, 0x2c, 0xc9, 0x90, 0x76, 0x66, 0x7b, 0x94, 0xe2, 0xaf, 0x78, 0xd6, 0x65, 0x53,
+ 0x5d, 0x3c, 0xd6, 0x9c, 0xb2, 0xcf, 0x29, 0x03, 0xf9, 0x2f, 0xa4, 0x50, 0xb2, 0xd4, 0x48, 0xce,
+ 0x05, 0x32, 0x55, 0x8a, 0xfd, 0xb2, 0x64, 0x4c, 0x0e, 0xe4, 0x98, 0x07, 0x75, 0xdb, 0x7f, 0xdf,
+ 0xb9, 0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xf9, 0x7b, 0x48, 0xa4, 0x69, 0x86, 0xe3, 0x35, 0x3f,
+ 0x1e, 0x86, 0x5d, 0x7a, 0x7a, 0x15, 0xbd, 0xef, 0x00, 0x8e, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90,
+ 0x26, 0x93, 0xbc, 0x0e, 0x49, 0x68, 0x91, 0xbf, 0xf8, 0x47, 0xd3, 0x9d, 0x95, 0x42, 0xc1, 0x0e,
+ 0x4d, 0xdf, 0x6f, 0x26, 0xcf, 0xc3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xd6, 0xd5, 0xc0, 0x07,
+ 0xe1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x74, 0x30, 0x72, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86,
+ 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x55, 0xe4, 0x81, 0xd1, 0x11, 0x80,
+ 0xbe, 0xd8, 0x89, 0xb9, 0x08, 0xa3, 0x31, 0xf9, 0xa1, 0x24, 0x09, 0x16, 0xb9, 0x70, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x55, 0xe4, 0x81, 0xd1, 0x11, 0x80, 0xbe,
+ 0xd8, 0x89, 0xb9, 0x08, 0xa3, 0x31, 0xf9, 0xa1, 0x24, 0x09, 0x16, 0xb9, 0x70, 0x30, 0x1d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf6, 0x7d, 0x07, 0x41, 0x00, 0x04, 0x10, 0x30, 0x0e, 0x1b, 0x08,
+ 0x56, 0x35, 0x2e, 0x30, 0x3a, 0x34, 0x2e, 0x30, 0x03, 0x02, 0x04, 0x90, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+ 0x59, 0x47, 0xac, 0x21, 0x84, 0x8a, 0x17, 0xc9, 0x9c, 0x89, 0x53, 0x1e, 0xba, 0x80, 0x85, 0x1a,
+ 0xc6, 0x3c, 0x4e, 0x3e, 0xb1, 0x9c, 0xb6, 0x7c, 0xc6, 0x92, 0x5d, 0x18, 0x64, 0x02, 0xe3, 0xd3,
+ 0x06, 0x08, 0x11, 0x61, 0x7c, 0x63, 0xe3, 0x2b, 0x9d, 0x31, 0x03, 0x70, 0x76, 0xd2, 0xa3, 0x28,
+ 0xa0, 0xf4, 0xbb, 0x9a, 0x63, 0x73, 0xed, 0x6d, 0xe5, 0x2a, 0xdb, 0xed, 0x14, 0xa9, 0x2b, 0xc6,
+ 0x36, 0x11, 0xd0, 0x2b, 0xeb, 0x07, 0x8b, 0xa5, 0xda, 0x9e, 0x5c, 0x19, 0x9d, 0x56, 0x12, 0xf5,
+ 0x54, 0x29, 0xc8, 0x05, 0xed, 0xb2, 0x12, 0x2a, 0x8d, 0xf4, 0x03, 0x1b, 0xff, 0xe7, 0x92, 0x10,
+ 0x87, 0xb0, 0x3a, 0xb5, 0xc3, 0x9d, 0x05, 0x37, 0x12, 0xa3, 0xc7, 0xf4, 0x15, 0xb9, 0xd5, 0xa4,
+ 0x39, 0x16, 0x9b, 0x53, 0x3a, 0x23, 0x91, 0xf1, 0xa8, 0x82, 0xa2, 0x6a, 0x88, 0x68, 0xc1, 0x79,
+ 0x02, 0x22, 0xbc, 0xaa, 0xa6, 0xd6, 0xae, 0xdf, 0xb0, 0x14, 0x5f, 0xb8, 0x87, 0xd0, 0xdd, 0x7c,
+ 0x7f, 0x7b, 0xff, 0xaf, 0x1c, 0xcf, 0xe6, 0xdb, 0x07, 0xad, 0x5e, 0xdb, 0x85, 0x9d, 0xd0, 0x2b,
+ 0x0d, 0x33, 0xdb, 0x04, 0xd1, 0xe6, 0x49, 0x40, 0x13, 0x2b, 0x76, 0xfb, 0x3e, 0xe9, 0x9c, 0x89,
+ 0x0f, 0x15, 0xce, 0x18, 0xb0, 0x85, 0x78, 0x21, 0x4f, 0x6b, 0x4f, 0x0e, 0xfa, 0x36, 0x67, 0xcd,
+ 0x07, 0xf2, 0xff, 0x08, 0xd0, 0xe2, 0xde, 0xd9, 0xbf, 0x2a, 0xaf, 0xb8, 0x87, 0x86, 0x21, 0x3c,
+ 0x04, 0xca, 0xb7, 0x94, 0x68, 0x7f, 0xcf, 0x3c, 0xe9, 0x98, 0xd7, 0x38, 0xff, 0xec, 0xc0, 0xd9,
+ 0x50, 0xf0, 0x2e, 0x4b, 0x58, 0xae, 0x46, 0x6f, 0xd0, 0x2e, 0xc3, 0x60, 0xda, 0x72, 0x55, 0x72,
+ 0xbd, 0x4c, 0x45, 0x9e, 0x61, 0xba, 0xbf, 0x84, 0x81, 0x92, 0x03, 0xd1, 0xd2, 0x69, 0x7c, 0xc5,
+};
+
+static void
+test_build_certificate_non_ca (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_VALUE, (void *)entrust_pretend_ca, sizeof (entrust_pretend_ca) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CERTIFICATE_CATEGORY, &other_entity, sizeof (other_entity) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, expected, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static const unsigned char verisign_v1_ca[] = {
+ 0x30, 0x82, 0x02, 0x3c, 0x30, 0x82, 0x01, 0xa5, 0x02, 0x10, 0x3f, 0x69, 0x1e, 0x81, 0x9c, 0xf0,
+ 0x9a, 0x4a, 0xf3, 0x73, 0xff, 0xb9, 0x48, 0xa2, 0xe4, 0xdd, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73,
+ 0x73, 0x20, 0x31, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61,
+ 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x36,
+ 0x30, 0x31, 0x32, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x38, 0x30,
+ 0x38, 0x30, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e,
+ 0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61,
+ 0x73, 0x73, 0x20, 0x31, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d,
+ 0x61, 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xe5, 0x19, 0xbf, 0x6d, 0xa3, 0x56, 0x61, 0x2d,
+ 0x99, 0x48, 0x71, 0xf6, 0x67, 0xde, 0xb9, 0x8d, 0xeb, 0xb7, 0x9e, 0x86, 0x80, 0x0a, 0x91, 0x0e,
+ 0xfa, 0x38, 0x25, 0xaf, 0x46, 0x88, 0x82, 0xe5, 0x73, 0xa8, 0xa0, 0x9b, 0x24, 0x5d, 0x0d, 0x1f,
+ 0xcc, 0x65, 0x6e, 0x0c, 0xb0, 0xd0, 0x56, 0x84, 0x18, 0x87, 0x9a, 0x06, 0x9b, 0x10, 0xa1, 0x73,
+ 0xdf, 0xb4, 0x58, 0x39, 0x6b, 0x6e, 0xc1, 0xf6, 0x15, 0xd5, 0xa8, 0xa8, 0x3f, 0xaa, 0x12, 0x06,
+ 0x8d, 0x31, 0xac, 0x7f, 0xb0, 0x34, 0xd7, 0x8f, 0x34, 0x67, 0x88, 0x09, 0xcd, 0x14, 0x11, 0xe2,
+ 0x4e, 0x45, 0x56, 0x69, 0x1f, 0x78, 0x02, 0x80, 0xda, 0xdc, 0x47, 0x91, 0x29, 0xbb, 0x36, 0xc9,
+ 0x63, 0x5c, 0xc5, 0xe0, 0xd7, 0x2d, 0x87, 0x7b, 0xa1, 0xb7, 0x32, 0xb0, 0x7b, 0x30, 0xba, 0x2a,
+ 0x2f, 0x31, 0xaa, 0xee, 0xa3, 0x67, 0xda, 0xdb, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x58, 0x15, 0x29, 0x39, 0x3c, 0x77, 0xa3, 0xda, 0x5c, 0x25, 0x03, 0x7c, 0x60, 0xfa, 0xee, 0x09,
+ 0x99, 0x3c, 0x27, 0x10, 0x70, 0xc8, 0x0c, 0x09, 0xe6, 0xb3, 0x87, 0xcf, 0x0a, 0xe2, 0x18, 0x96,
+ 0x35, 0x62, 0xcc, 0xbf, 0x9b, 0x27, 0x79, 0x89, 0x5f, 0xc9, 0xc4, 0x09, 0xf4, 0xce, 0xb5, 0x1d,
+ 0xdf, 0x2a, 0xbd, 0xe5, 0xdb, 0x86, 0x9c, 0x68, 0x25, 0xe5, 0x30, 0x7c, 0xb6, 0x89, 0x15, 0xfe,
+ 0x67, 0xd1, 0xad, 0xe1, 0x50, 0xac, 0x3c, 0x7c, 0x62, 0x4b, 0x8f, 0xba, 0x84, 0xd7, 0x12, 0x15,
+ 0x1b, 0x1f, 0xca, 0x5d, 0x0f, 0xc1, 0x52, 0x94, 0x2a, 0x11, 0x99, 0xda, 0x7b, 0xcf, 0x0c, 0x36,
+ 0x13, 0xd5, 0x35, 0xdc, 0x10, 0x19, 0x59, 0xea, 0x94, 0xc1, 0x00, 0xbf, 0x75, 0x8f, 0xd9, 0xfa,
+ 0xfd, 0x76, 0x04, 0xdb, 0x62, 0xbb, 0x90, 0x6a, 0x03, 0xd9, 0x46, 0x35, 0xd9, 0xf8, 0x7c, 0x5b,
+};
+
+static void
+test_build_certificate_v1_ca (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CERTIFICATE_CATEGORY, &certificate_authority, sizeof (certificate_authority) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, expected, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_build_certificate_staple_ca (CuTest *cu)
+{
+ CK_ULONG category = 2; /* CA */
+
+ CK_ATTRIBUTE stapled[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension) },
+ { CKA_OBJECT_ID, (void *)P11_OID_BASIC_CONSTRAINTS, sizeof (P11_OID_BASIC_CONSTRAINTS) },
+ { CKA_VALUE, "\x30\x03\x01\x01\xFF", 5 },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_VALUE, (void *)entrust_pretend_ca, sizeof (entrust_pretend_ca) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ /* Add a stapled certificate */
+ rv = p11_index_add (test.index, stapled, 4, NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ /*
+ * Even though the certificate is not a valid CA, the presence of the
+ * stapled certificate extension transforms it into a CA.
+ */
+ test_check_attrs (cu, expected, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_build_certificate_no_type (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCOMPLETE, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_build_certificate_bad_type (CuTest *cu)
+{
+ CK_CERTIFICATE_TYPE type = CKC_WTLS;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCONSISTENT, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_build_extension (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension) },
+ { CKA_OBJECT_ID, "\x06\x03\x55\x1d\x50", 5 },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE check[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension) },
+ { CKA_TOKEN, &truev, sizeof (truev) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_PRIVATE, &falsev, sizeof (falsev) },
+ { CKA_OBJECT_ID, "\x06\x03\x55\x1d\x50", 5 },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_LABEL, "", 0 },
+ { CKA_X_CRITICAL, &falsev, sizeof (falsev) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, check, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_create_not_settable (CuTest *cu)
+{
+ /*
+ * CKA_TRUSTED cannot be set by the normal user according to spec
+ */
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_TRUSTED, &falsev, sizeof (falsev) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_ATTRIBUTE_READ_ONLY, rv);
+
+ p11_message_loud ();
+
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_create_but_loadable (CuTest *cu)
+{
+ /*
+ * CKA_TRUSTED cannot be set on creation, but can be set if we're
+ * loading from our store. This is signified by batching.
+ */
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_TRUSTED, &falsev, sizeof (falsev) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_index_batch (test.index);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ p11_index_finish (test.index);
+
+ test_check_attrs (cu, input, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_create_unsupported (CuTest *cu)
+{
+ CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCONSISTENT, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_create_generated (CuTest *cu)
+{
+ CK_OBJECT_CLASS klass = CKO_NSS_TRUST;
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCONSISTENT, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_create_bad_attribute (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_COLOR, "blue", 4 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCONSISTENT, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_create_missing_attribute (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCOMPLETE, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_create_no_class (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCOMPLETE, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_create_token_mismatch (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_TOKEN, &falsev, sizeof (falsev) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_message_quiet ();
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_TEMPLATE_INCONSISTENT, rv);
+
+ p11_message_loud ();
+
+ teardown (cu);
+}
+
+static void
+test_modify_success (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_MODIFIABLE, &truev, sizeof (truev) },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE modify[] = {
+ { CKA_VALUE, "new value long", 14 },
+ { CKA_LABEL, "new label", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_MODIFIABLE, &truev, sizeof (truev) },
+ { CKA_VALUE, "new value long", 14 },
+ { CKA_LABEL, "new label", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (modify));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, expected, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_modify_read_only (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_MODIFIABLE, &truev, sizeof (truev) },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE modify[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_ATTRIBUTE *merge;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ merge = p11_attrs_dup (input);
+ rv = p11_builder_build (test.builder, test.index, &attrs, merge);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ p11_message_quiet ();
+
+ merge = p11_attrs_dup (modify);
+ rv = p11_builder_build (test.builder, test.index, &attrs, merge);
+ CuAssertIntEquals (cu, CKR_ATTRIBUTE_READ_ONLY, rv);
+
+ p11_message_loud ();
+
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_modify_unchanged (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_MODIFIABLE, &truev, sizeof (truev) },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ /*
+ * Although CKA_CLASS is read-only, changing to same value
+ * shouldn't fail
+ */
+
+ CK_ATTRIBUTE modify[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_VALUE, "the other", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_VALUE, "the other", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (modify));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ test_check_attrs (cu, expected, attrs);
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_modify_not_modifiable (CuTest *cu)
+{
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &data, sizeof (data) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE modify[] = {
+ { CKA_VALUE, "the value", 9 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (input));
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ p11_message_quiet ();
+
+ rv = p11_builder_build (test.builder, test.index, &attrs, p11_attrs_dup (modify));
+ CuAssertIntEquals (cu, CKR_ATTRIBUTE_READ_ONLY, rv);
+
+ p11_message_loud ();
+
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_changed_trusted_certificate (CuTest *cu)
+{
+ static CK_ATTRIBUTE cacert3_trusted_certificate[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CERTIFICATE_CATEGORY, &certificate_authority, sizeof (certificate_authority) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_CHECK_VALUE, "\xad\x7c\x3f", 3 },
+ { CKA_START_DATE, "20110523", 8 },
+ { CKA_END_DATE, "20210520", 8, },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_TRUSTED, &truev, sizeof (truev) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_INVALID },
+ };
+
+ static unsigned char eku_server_and_client[] = {
+ 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x03, 0x02,
+ };
+
+ CK_ATTRIBUTE eku_extension_server_and_client[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
+ { CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE, sizeof (P11_OID_EXTENDED_KEY_USAGE) },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_X_CRITICAL, &truev, sizeof (truev) },
+ { CKA_VALUE, eku_server_and_client, sizeof (eku_server_and_client) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static char eku_client_email[] = {
+ 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04,
+ };
+
+ static CK_ATTRIBUTE reject_extension_email[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
+ { CKA_OBJECT_ID, (void *)P11_OID_OPENSSL_REJECT, sizeof (P11_OID_OPENSSL_REJECT) },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_X_CRITICAL, &falsev, sizeof (falsev) },
+ { CKA_VALUE, eku_client_email, sizeof (eku_client_email) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE nss_trust_server_and_client_distrust_email[] = {
+ { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
+ { CKA_CERT_MD5_HASH, "\xf7\x25\x12\x82\x4e\x67\xb5\xd0\x8d\x92\xb7\x7c\x0b\x86\x7a\x42", 16 },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_TRUST_SERVER_AUTH, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_CLIENT_AUTH, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_EMAIL_PROTECTION, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_CODE_SIGNING, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_IPSEC_END_SYSTEM, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_IPSEC_TUNNEL, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_IPSEC_USER, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_TIME_STAMPING, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_DIGITAL_SIGNATURE, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_NON_REPUDIATION, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_KEY_ENCIPHERMENT, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_DATA_ENCIPHERMENT, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_KEY_AGREEMENT, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_KEY_CERT_SIGN, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_TRUST_CRL_SIGN, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_INVALID, }
+ };
+
+ static CK_ATTRIBUTE server_anchor_assertion[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, sizeof (P11_OID_SERVER_AUTH_STR) - 1 },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE client_anchor_assertion[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, sizeof (P11_OID_CLIENT_AUTH_STR) - 1 },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE email_distrust_assertion[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, sizeof (P11_OID_EMAIL_PROTECTION_STR) - 1 },
+ { CKA_LABEL, "Custom Label", 12 },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ /*
+ * We should get an NSS trust object and various assertions here.
+ * The first two attributes of each object are enough to look it up,
+ * and then we check the rest of the attributes match.
+ */
+
+ CK_ATTRIBUTE *expected[] = {
+ nss_trust_server_and_client_distrust_email,
+ email_distrust_assertion,
+ server_anchor_assertion,
+ client_anchor_assertion,
+ NULL,
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+ int i;
+
+ setup (cu);
+
+ /*
+ * A trusted cetrificate, trusted for server and client purposes,
+ * and explicitly rejects the email and timestamping purposes.
+ */
+ p11_index_batch (test.index);
+ rv = p11_index_take (test.index, p11_attrs_dup (cacert3_trusted_certificate), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ rv = p11_index_take (test.index, p11_attrs_dup (eku_extension_server_and_client), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ rv = p11_index_take (test.index, p11_attrs_dup (reject_extension_email), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ p11_index_finish (test.index);
+
+
+ /* The other objects */
+ for (i = 0; expected[i]; i++) {
+ handle = p11_index_findn (test.index, expected[i], 2);
+ CuAssertTrue (cu, handle != 0);
+
+ attrs = p11_index_lookup (test.index, handle);
+ CuAssertPtrNotNull (cu, attrs);
+
+ test_check_attrs (cu, expected[i], attrs);
+ }
+
+ teardown (cu);
+}
+
+static void
+test_changed_distrusted (CuTest *cu)
+{
+ CK_ATTRIBUTE distrust_cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate), },
+ { CKA_CERTIFICATE_CATEGORY, &certificate_authority, sizeof (certificate_authority) },
+ { CKA_PRIVATE, &falsev, sizeof (falsev) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_TRUSTED, &falsev, sizeof (falsev) },
+ { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE eku_extension[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
+ { CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE, sizeof (P11_OID_EXTENDED_KEY_USAGE) },
+ { CKA_X_CRITICAL, &truev, sizeof (truev) },
+ { CKA_VALUE, "\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x99\x77\x06\x0a\x10", 14 },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE reject_extension[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
+ { CKA_OBJECT_ID, (void *)P11_OID_OPENSSL_REJECT, sizeof (P11_OID_OPENSSL_REJECT) },
+ { CKA_X_CRITICAL, &falsev, sizeof (falsev) },
+ { CKA_VALUE, "\x30\x0a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02", 12 },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE nss_trust_nothing[] = {
+ { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+ { CKA_ID, "the id", 6 },
+ { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
+ { CKA_CERT_MD5_HASH, "\xf7\x25\x12\x82\x4e\x67\xb5\xd0\x8d\x92\xb7\x7c\x0b\x86\x7a\x42", 16 },
+ { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_TRUST_SERVER_AUTH, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_CLIENT_AUTH, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_EMAIL_PROTECTION, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_CODE_SIGNING, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_IPSEC_END_SYSTEM, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_IPSEC_TUNNEL, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_IPSEC_USER, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_TIME_STAMPING, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_DIGITAL_SIGNATURE, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_NON_REPUDIATION, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_KEY_ENCIPHERMENT, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_DATA_ENCIPHERMENT, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_KEY_AGREEMENT, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_KEY_CERT_SIGN, &not_trusted, sizeof (not_trusted) },
+ { CKA_TRUST_CRL_SIGN, &not_trusted, sizeof (not_trusted) },
+ { CKA_INVALID, }
+ };
+
+ CK_ATTRIBUTE server_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE client_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE code_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, strlen (P11_OID_CODE_SIGNING_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE email_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE ipsec_system_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, strlen (P11_OID_IPSEC_END_SYSTEM_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE ipsec_tunnel_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, strlen (P11_OID_IPSEC_TUNNEL_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE ipsec_user_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, strlen (P11_OID_IPSEC_USER_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE stamping_distrust[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, strlen (P11_OID_TIME_STAMPING_STR) },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ /*
+ * We should get an NSS trust object and various assertions here.
+ * The first two attributes of each object are enough to look it up,
+ * and then we check the rest of the attributes match.
+ */
+
+ CK_ATTRIBUTE *expected[] = {
+ nss_trust_nothing,
+ server_distrust,
+ client_distrust,
+ code_distrust,
+ email_distrust,
+ ipsec_system_distrust,
+ ipsec_tunnel_distrust,
+ ipsec_user_distrust,
+ stamping_distrust,
+ NULL
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+ int i;
+
+ setup (cu);
+
+ /*
+ * A trusted cetrificate, trusted for server and client purposes,
+ * and explicitly rejects the email and timestamping purposes.
+ */
+ p11_index_batch (test.index);
+ rv = p11_index_take (test.index, p11_attrs_dup (distrust_cert), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ rv = p11_index_take (test.index, p11_attrs_dup (eku_extension), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ rv = p11_index_take (test.index, p11_attrs_dup (reject_extension), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ p11_index_finish (test.index);
+
+ /* The other objects */
+ for (i = 0; expected[i]; i++) {
+ handle = p11_index_findn (test.index, expected[i], 2);
+ CuAssertTrue (cu, handle != 0);
+
+ attrs = p11_index_lookup (test.index, handle);
+ CuAssertPtrNotNull (cu, attrs);
+
+ test_check_attrs (cu, expected[i], attrs);
+ }
+
+ teardown (cu);
+}
+
+static void
+test_changed_dup_certificates (CuTest *cu)
+{
+ static CK_ATTRIBUTE trusted_cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CERTIFICATE_CATEGORY, &certificate_authority, sizeof (certificate_authority) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_TRUSTED, &truev, sizeof (truev) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE distrust_cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CERTIFICATE_CATEGORY, &certificate_authority, sizeof (certificate_authority) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE trusted_nss[] = {
+ { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+ { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
+ { CKA_TRUST_SERVER_AUTH, &trusted_delegator, sizeof (trusted_delegator) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID, }
+ };
+
+ static CK_ATTRIBUTE distrust_nss[] = {
+ { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+ { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
+ { CKA_TRUST_SERVER_AUTH, &not_trusted, sizeof (not_trusted) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID, }
+ };
+
+ static CK_ATTRIBUTE match_nss[] = {
+ { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID, }
+ };
+
+ static CK_ATTRIBUTE anchor_assertion[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, sizeof (P11_OID_SERVER_AUTH_STR) - 1 },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE distrust_assertion[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, sizeof (P11_OID_SERVER_AUTH_STR) - 1 },
+ { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+ { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+ { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE match_assertion[] = {
+ { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ { CKA_ID, "cacert3", 7 },
+ { CKA_INVALID, }
+ };
+
+ CK_OBJECT_HANDLE handle1;
+ CK_OBJECT_HANDLE handle2;
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ setup (cu);
+
+ /*
+ * A trusted certificate, should create trutsed nss trust
+ * and anchor assertions
+ */
+ p11_index_batch (test.index);
+ rv = p11_index_take (test.index, p11_attrs_dup (trusted_cert), &handle1);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ p11_index_finish (test.index);
+
+ handle = p11_index_find (test.index, match_nss);
+ CuAssertTrue (cu, handle != 0);
+ handle = p11_index_find (test.index, match_assertion);
+ CuAssertTrue (cu, handle != 0);
+ handle = p11_index_find (test.index, trusted_nss);
+ CuAssertTrue (cu, handle != 0);
+ handle = p11_index_find (test.index, anchor_assertion);
+ CuAssertTrue (cu, handle != 0);
+
+ /* Now we add a distrusted certificate, should update the objects */
+ p11_index_batch (test.index);
+ rv = p11_index_take (test.index, p11_attrs_dup (distrust_cert), &handle2);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ p11_index_finish (test.index);
+
+ handle = p11_index_find (test.index, trusted_nss);
+ CuAssertTrue (cu, handle == 0);
+ handle = p11_index_find (test.index, distrust_nss);
+ CuAssertTrue (cu, handle != 0);
+ handle = p11_index_find (test.index, anchor_assertion);
+ CuAssertTrue (cu, handle == 0);
+ handle = p11_index_find (test.index, distrust_assertion);
+ CuAssertTrue (cu, handle != 0);
+
+ /* Now remove the trusted cetrificate, should update again */
+ rv = p11_index_remove (test.index, handle2);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ handle = p11_index_find (test.index, trusted_nss);
+ CuAssertTrue (cu, handle != 0);
+ handle = p11_index_find (test.index, distrust_nss);
+ CuAssertTrue (cu, handle == 0);
+ handle = p11_index_find (test.index, anchor_assertion);
+ CuAssertTrue (cu, handle != 0);
+ handle = p11_index_find (test.index, distrust_assertion);
+ CuAssertTrue (cu, handle == 0);
+
+ /* Now remove the original certificate, no more nss/assertions */
+ rv = p11_index_remove (test.index, handle1);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ handle = p11_index_find (test.index, match_nss);
+ CuAssertTrue (cu, handle == 0);
+ handle = p11_index_find (test.index, match_assertion);
+ CuAssertTrue (cu, handle == 0);
+
+ teardown (cu);
+}
+
+static void
+test_changed_without_id (CuTest *cu)
+{
+ static CK_ATTRIBUTE trusted_without_id[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CERTIFICATE_CATEGORY, &certificate_authority, sizeof (certificate_authority) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_TRUSTED, &truev, sizeof (truev) },
+ { CKA_INVALID },
+ };
+
+ CK_OBJECT_CLASS klass = 0;
+ CK_ATTRIBUTE match[] = {
+ { CKA_CLASS, &klass, sizeof (klass) },
+ { CKA_INVALID },
+ };
+
+ /*
+ * A cetrificate without a CKA_ID that's created should not
+ * automatically create any compat objects.
+ */
+
+ CK_OBJECT_HANDLE handle;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_index_batch (test.index);
+ rv = p11_index_take (test.index, p11_attrs_dup (trusted_without_id), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ p11_index_finish (test.index);
+
+ klass = CKO_NSS_TRUST;
+ handle = p11_index_find (test.index, match);
+ CuAssertIntEquals (cu, 0, handle);
+
+ klass = CKO_X_TRUST_ASSERTION;
+ handle = p11_index_find (test.index, match);
+ CuAssertIntEquals (cu, 0, handle);
+
+ teardown (cu);
+}
+
+static void
+test_changed_staple_ca (CuTest *cu)
+{
+ CK_ULONG category = 0;
+
+ CK_ATTRIBUTE stapled[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension) },
+ { CKA_OBJECT_ID, (void *)P11_OID_BASIC_CONSTRAINTS, sizeof (P11_OID_BASIC_CONSTRAINTS) },
+ { CKA_VALUE, "\x30\x03\x01\x01\xFF", 5 },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_VALUE, (void *)entrust_pretend_ca, sizeof (entrust_pretend_ca) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE match[] = {
+ { CKA_VALUE, (void *)entrust_pretend_ca, sizeof (entrust_pretend_ca) },
+ { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ attrs = NULL;
+ rv = p11_index_take (test.index, p11_attrs_dup (input), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ /* Not a CA at this point, until we staple */
+ category = 0;
+ CuAssertTrue (cu, p11_index_find (test.index, match) == 0);
+
+ /* Add a stapled basic constraint */
+ rv = p11_index_add (test.index, stapled, 4, NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+
+ /* Now should be a CA */
+ category = 2;
+ CuAssertTrue (cu, p11_index_find (test.index, match) != 0);
+
+ p11_attrs_free (attrs);
+
+ teardown (cu);
+}
+
+static void
+test_changed_staple_ku (CuTest *cu)
+{
+ CK_ATTRIBUTE stapled_ds_and_np[] = {
+ { CKA_CLASS, &certificate_extension, sizeof (certificate_extension) },
+ { CKA_OBJECT_ID, (void *)P11_OID_KEY_USAGE, sizeof (P11_OID_KEY_USAGE) },
+ { CKA_VALUE, "\x03\x03\x07\xc0\x00", 5 },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ CK_ATTRIBUTE input[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_VALUE, (void *)entrust_pretend_ca, sizeof (entrust_pretend_ca) },
+ { CKA_TRUSTED, &truev, sizeof (truev) },
+ { CKA_ID, "the id", 6 },
+ { CKA_INVALID },
+ };
+
+ static CK_ATTRIBUTE nss_trust_ds_and_np[] = {
+ { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+ { CKA_ID, "the id", 6 },
+ { CKA_TRUST_SERVER_AUTH, &trusted, sizeof (trusted) },
+ { CKA_TRUST_CLIENT_AUTH, &trusted, sizeof (trusted) },
+ { CKA_TRUST_EMAIL_PROTECTION, &trusted, sizeof (trusted) },
+ { CKA_TRUST_CODE_SIGNING, &trusted, sizeof (trusted) },
+ { CKA_TRUST_IPSEC_END_SYSTEM, &trusted, sizeof (trusted) },
+ { CKA_TRUST_IPSEC_TUNNEL, &trusted, sizeof (trusted) },
+ { CKA_TRUST_IPSEC_USER, &trusted, sizeof (trusted) },
+ { CKA_TRUST_TIME_STAMPING, &trusted, sizeof (trusted) },
+ { CKA_TRUST_DIGITAL_SIGNATURE, &trusted, sizeof (trusted) },
+ { CKA_TRUST_NON_REPUDIATION, &trusted, sizeof (trusted) },
+ { CKA_TRUST_KEY_ENCIPHERMENT, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_DATA_ENCIPHERMENT, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_KEY_AGREEMENT, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_KEY_CERT_SIGN, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_TRUST_CRL_SIGN, &trust_unknown, sizeof (trust_unknown) },
+ { CKA_INVALID, }
+ };
+
+ CK_OBJECT_HANDLE handle;
+ CK_ATTRIBUTE *attrs;
+ CK_RV rv;
+
+ setup (cu);
+
+ p11_index_batch (test.index);
+ rv = p11_index_take (test.index, p11_attrs_dup (input), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ rv = p11_index_take (test.index, p11_attrs_dup (stapled_ds_and_np), NULL);
+ CuAssertIntEquals (cu, CKR_OK, rv);
+ p11_index_finish (test.index);
+
+ handle = p11_index_findn (test.index, nss_trust_ds_and_np, 2);
+ CuAssertTrue (cu, handle != 0);
+
+ attrs = p11_index_lookup (test.index, handle);
+ test_check_attrs (cu, nss_trust_ds_and_np, attrs);
+
+ teardown (cu);
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ putenv ("P11_KIT_STRICT=1");
+ p11_library_init ();
+ p11_debug_init ();
+ /* p11_message_quiet (); */
+
+ SUITE_ADD_TEST (suite, test_get_cache);
+ SUITE_ADD_TEST (suite, test_build_data);
+ SUITE_ADD_TEST (suite, test_build_certificate);
+ SUITE_ADD_TEST (suite, test_build_certificate_empty);
+ SUITE_ADD_TEST (suite, test_build_certificate_non_ca);
+ SUITE_ADD_TEST (suite, test_build_certificate_v1_ca);
+ SUITE_ADD_TEST (suite, test_build_certificate_staple_ca);
+ SUITE_ADD_TEST (suite, test_build_certificate_no_type);
+ SUITE_ADD_TEST (suite, test_build_certificate_bad_type);
+ SUITE_ADD_TEST (suite, test_build_extension);
+ SUITE_ADD_TEST (suite, test_create_not_settable);
+ SUITE_ADD_TEST (suite, test_create_but_loadable);
+ SUITE_ADD_TEST (suite, test_create_unsupported);
+ SUITE_ADD_TEST (suite, test_create_generated);
+ SUITE_ADD_TEST (suite, test_create_bad_attribute);
+ SUITE_ADD_TEST (suite, test_create_missing_attribute);
+ SUITE_ADD_TEST (suite, test_create_no_class);
+ SUITE_ADD_TEST (suite, test_create_token_mismatch);
+ SUITE_ADD_TEST (suite, test_modify_success);
+ SUITE_ADD_TEST (suite, test_modify_read_only);
+ SUITE_ADD_TEST (suite, test_modify_unchanged);
+ SUITE_ADD_TEST (suite, test_modify_not_modifiable);
+
+ SUITE_ADD_TEST (suite, test_changed_trusted_certificate);
+ SUITE_ADD_TEST (suite, test_changed_distrusted);
+ SUITE_ADD_TEST (suite, test_changed_without_id);
+ SUITE_ADD_TEST (suite, test_changed_staple_ca);
+ SUITE_ADD_TEST (suite, test_changed_staple_ku);
+ SUITE_ADD_TEST (suite, test_changed_dup_certificates);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}
diff --git a/trust/tests/test-data.c b/trust/tests/test-data.c
index f159926..0ddc4c6 100644
--- a/trust/tests/test-data.c
+++ b/trust/tests/test-data.c
@@ -51,11 +51,9 @@ test_check_object_msg (CuTest *cu,
CK_OBJECT_CLASS klass,
const char *label)
{
- CK_BBOOL vtrue = CK_TRUE;
CK_BBOOL vfalse = CK_FALSE;
CK_ATTRIBUTE expected[] = {
- { CKA_TOKEN, &vtrue, sizeof (vtrue) },
{ CKA_PRIVATE, &vfalse, sizeof (vfalse) },
{ CKA_MODIFIABLE, &vfalse, sizeof (vfalse) },
{ CKA_CLASS, &klass, sizeof (klass) },
diff --git a/trust/tests/test-module.c b/trust/tests/test-module.c
index ddc31df..9c633f0 100644
--- a/trust/tests/test-module.c
+++ b/trust/tests/test-module.c
@@ -59,6 +59,8 @@
*/
#define NUM_SLOTS 3
+static CK_OBJECT_CLASS data = CKO_DATA;
+
struct {
CK_FUNCTION_LIST *module;
CK_SLOT_ID slots[NUM_SLOTS];
@@ -357,7 +359,7 @@ check_trust_object_equiv (CuTest *cu,
};
rv = test.module->C_GetAttributeValue (session, trust, equiv, 6);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
test_check_attrs (cu, equiv, cert);
}
@@ -551,6 +553,7 @@ static void
test_session_object (CuTest *cu)
{
CK_ATTRIBUTE original[] = {
+ { CKA_CLASS, &data, sizeof (data) },
{ CKA_LABEL, "yay", 3 },
{ CKA_VALUE, "eight", 5 },
{ CKA_INVALID }
@@ -579,6 +582,7 @@ static void
test_session_find (CuTest *cu)
{
CK_ATTRIBUTE original[] = {
+ { CKA_CLASS, &data, sizeof (data) },
{ CKA_LABEL, "yay", 3 },
{ CKA_VALUE, "eight", 5 },
{ CKA_INVALID }
@@ -593,21 +597,21 @@ test_session_find (CuTest *cu)
setup (cu);
rv = test.module->C_OpenSession (test.slots[0], CKF_SERIAL_SESSION, NULL, NULL, &session);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
rv = test.module->C_CreateObject (session, original, 2, &handle);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
rv = test.module->C_FindObjectsInit (session, original, 2);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
rv = test.module->C_FindObjects (session, &check, 1, &count);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
CuAssertIntEquals (cu, 1, count);
CuAssertIntEquals (cu, handle, check);
rv = test.module->C_FindObjectsFinal (session);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
teardown (cu);
}
@@ -660,6 +664,7 @@ static void
test_setattr_token (CuTest *cu)
{
CK_ATTRIBUTE original[] = {
+ { CKA_CLASS, &data, sizeof (data) },
{ CKA_LABEL, "yay", 3 },
{ CKA_VALUE, "eight", 5 },
{ CKA_INVALID }
@@ -692,6 +697,7 @@ static void
test_session_copy (CuTest *cu)
{
CK_ATTRIBUTE original[] = {
+ { CKA_CLASS, &data, sizeof (data) },
{ CKA_LABEL, "yay", 3 },
{ CKA_VALUE, "eight", 5 },
{ CKA_INVALID }
@@ -706,16 +712,16 @@ test_session_copy (CuTest *cu)
setup (cu);
rv = test.module->C_OpenSession (test.slots[0], CKF_SERIAL_SESSION, NULL, NULL, &session);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
rv = test.module->C_CreateObject (session, original, 2, &handle);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
rv = test.module->C_CopyObject (session, handle, original, 2, &copy);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
rv = test.module->C_GetObjectSize (session, copy, &size);
- CuAssertTrue (cu, rv == CKR_OK);
+ CuAssertIntEquals (cu, CKR_OK, rv);
teardown (cu);
}
@@ -724,6 +730,7 @@ static void
test_session_setattr (CuTest *cu)
{
CK_ATTRIBUTE original[] = {
+ { CKA_CLASS, &data, sizeof (data) },
{ CKA_LABEL, "yay", 3 },
{ CKA_VALUE, "eight", 5 },
{ CKA_INVALID }
@@ -751,6 +758,7 @@ static void
test_session_remove (CuTest *cu)
{
CK_ATTRIBUTE original[] = {
+ { CKA_CLASS, &data, sizeof (data) },
{ CKA_LABEL, "yay", 3 },
{ CKA_VALUE, "eight", 5 },
{ CKA_INVALID }
diff --git a/trust/tests/test-parser.c b/trust/tests/test-parser.c
index 0f40748..3ad89da 100644
--- a/trust/tests/test-parser.c
+++ b/trust/tests/test-parser.c
@@ -41,6 +41,7 @@
#include "array.h"
#include "attrs.h"
+#include "builder.h"
#include "debug.h"
#include "library.h"
#include "oid.h"
@@ -50,69 +51,75 @@
struct {
p11_parser *parser;
- p11_array *objects;
+ p11_asn1_cache *cache;
+ p11_index *index;
} test;
static void
setup (CuTest *cu)
{
- test.parser = p11_parser_new ();
+ test.index = p11_index_new (NULL, NULL, NULL);
+ test.cache = p11_asn1_cache_new ();
+ test.parser = p11_parser_new (test.index, test.cache);
CuAssertPtrNotNull (cu, test.parser);
-
- test.objects = p11_array_new (p11_attrs_free);
- CuAssertPtrNotNull (cu, test.objects);
}
static void
teardown (CuTest *cu)
{
p11_parser_free (test.parser);
- p11_array_free (test.objects);
+ p11_index_free (test.index);
+ p11_asn1_cache_free (test.cache);
memset (&test, 0, sizeof (test));
}
-static void
-on_parse_object (CK_ATTRIBUTE *attrs,
- void *data)
-{
- CuTest *cu = data;
+static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
+static CK_OBJECT_CLASS certificate_extension = CKO_X_CERTIFICATE_EXTENSION;
+static CK_BBOOL falsev = CK_FALSE;
+static CK_BBOOL truev = CK_TRUE;
+static CK_CERTIFICATE_TYPE x509 = CKC_X_509;
- CuAssertPtrNotNull (cu, attrs);
- CuAssertTrue (cu, p11_attrs_count (attrs) > 0);
+static CK_ATTRIBUTE certificate_match[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_INVALID, },
+};
+
+static CK_ATTRIBUTE *
+parsed_attrs (CK_ATTRIBUTE *match)
+{
+ CK_OBJECT_HANDLE handle;
+ handle = p11_index_find (test.index, certificate_match);
+ return p11_index_lookup (test.index, handle);
- p11_array_push (test.objects, attrs);
}
static void
test_parse_der_certificate (CuTest *cu)
{
CK_ATTRIBUTE *cert;
- CK_ATTRIBUTE *object;
- CK_BBOOL bval;
int ret;
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_TRUSTED, &falsev, sizeof (falsev) },
+ { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
+ { CKA_INVALID },
+ };
+
setup (cu);
ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
- 0, on_parse_object, cu);
+ P11_PARSE_FLAG_NONE);
CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
- /* Should have gotten certificate and a trust object */
- CuAssertIntEquals (cu, 2, test.objects->num);
-
- cert = test.objects->elem[0];
- test_check_cacert3_ca (cu, cert, NULL);
-
- if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &bval))
- CuFail (cu, "missing CKA_TRUSTED");
- CuAssertIntEquals (cu, CK_FALSE, bval);
+ /* Should have gotten certificate */
+ CuAssertIntEquals (cu, 1, p11_index_size (test.index));
- if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &bval))
- CuFail (cu, "missing CKA_X_DISTRUSTED");
- CuAssertIntEquals (cu, CK_FALSE, bval);
-
- object = test.objects->elem[1];
- test_check_id (cu, cert, object);
+ cert = parsed_attrs (certificate_match);
+ test_check_attrs (cu, expected, cert);
teardown (cu);
}
@@ -121,32 +128,29 @@ static void
test_parse_pem_certificate (CuTest *cu)
{
CK_ATTRIBUTE *cert;
- CK_ATTRIBUTE *object;
- CK_BBOOL bval;
int ret;
+ CK_ATTRIBUTE expected[] = {
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_TRUSTED, &falsev, sizeof (falsev) },
+ { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
+ { CKA_INVALID },
+ };
+
setup (cu);
ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.pem",
- 0, on_parse_object, cu);
+ P11_PARSE_FLAG_NONE);
CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
- /* Should have gotten certificate and a trust object */
- CuAssertIntEquals (cu, 2, test.objects->num);
+ /* Should have gotten certificate */
+ CuAssertIntEquals (cu, 1, p11_index_size (test.index));
- cert = test.objects->elem[0];
- test_check_cacert3_ca (cu, cert, NULL);
-
- if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &bval))
- CuFail (cu, "missing CKA_TRUSTED");
- CuAssertIntEquals (cu, CK_FALSE, bval);
-
- if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &bval))
- CuFail (cu, "missing CKA_X_DISTRUSTED");
- CuAssertIntEquals (cu, CK_FALSE, bval);
-
- object = test.objects->elem[1];
- test_check_id (cu, cert, object);
+ cert = parsed_attrs (certificate_match);
+ test_check_attrs (cu, expected, cert);
teardown (cu);
}
@@ -154,136 +158,71 @@ test_parse_pem_certificate (CuTest *cu)
static void
test_parse_openssl_trusted (CuTest *cu)
{
- CK_TRUST trusted = CKT_NSS_TRUSTED_DELEGATOR;
- CK_TRUST distrusted = CKT_NSS_NOT_TRUSTED;
- CK_TRUST unknown = CKT_NSS_TRUST_UNKNOWN;
- CK_OBJECT_CLASS certificate_extension = CKO_X_CERTIFICATE_EXTENSION;
- CK_OBJECT_CLASS trust_object = CKO_NSS_TRUST;
- CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION;
- CK_X_ASSERTION_TYPE anchored_certificate = CKT_X_ANCHORED_CERTIFICATE;
- CK_X_ASSERTION_TYPE distrusted_certificate = CKT_X_DISTRUSTED_CERTIFICATE;
- CK_BBOOL vtrue = CK_TRUE;
- CK_BBOOL vfalse = CK_FALSE;
+ CK_ATTRIBUTE cacert3[] = {
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
+ { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_TRUSTED, &truev, sizeof (truev) },
+ { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
+ { CKA_INVALID },
+ };
CK_ATTRIBUTE eku_extension[] = {
- { CKA_LABEL, "Custom Label", 12 },
{ CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
{ CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE, sizeof (P11_OID_EXTENDED_KEY_USAGE) },
- { CKA_X_CRITICAL, &vtrue, sizeof (vtrue) },
+ { CKA_X_CRITICAL, &truev, sizeof (truev) },
{ CKA_VALUE, "\x30\x14\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2b\x06"
"\x01\x05\x05\x07\x03\x02", 22 },
{ CKA_INVALID },
};
CK_ATTRIBUTE reject_extension[] = {
- { CKA_LABEL, "Custom Label", 12 },
{ CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
{ CKA_OBJECT_ID, (void *)P11_OID_OPENSSL_REJECT, sizeof (P11_OID_OPENSSL_REJECT) },
- { CKA_X_CRITICAL, &vfalse, sizeof (vfalse) },
+ { CKA_X_CRITICAL, &falsev, sizeof (falsev) },
{ CKA_VALUE, "\x30\x0a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04", 12 },
{ CKA_INVALID },
};
- CK_ATTRIBUTE nss_trust[] = {
- { CKA_LABEL, "Custom Label", 12 },
- { CKA_CLASS, &trust_object, sizeof (trust_object), },
- { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
- { CKA_CERT_MD5_HASH, "\xf7\x25\x12\x82\x4e\x67\xb5\xd0\x8d\x92\xb7\x7c\x0b\x86\x7a\x42", 16 },
- { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
- { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
- { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
- { CKA_TRUST_SERVER_AUTH, &trusted, sizeof (trusted) },
- { CKA_TRUST_CLIENT_AUTH, &trusted, sizeof (trusted) },
- { CKA_TRUST_EMAIL_PROTECTION, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_CODE_SIGNING, &unknown, sizeof (unknown) },
- { CKA_TRUST_IPSEC_END_SYSTEM, &unknown, sizeof (unknown) },
- { CKA_TRUST_IPSEC_TUNNEL, &unknown, sizeof (unknown) },
- { CKA_TRUST_IPSEC_USER, &unknown, sizeof (unknown) },
- { CKA_TRUST_TIME_STAMPING, &unknown, sizeof (unknown) },
- { CKA_TRUST_DIGITAL_SIGNATURE, &trusted, sizeof (trusted) },
- { CKA_TRUST_NON_REPUDIATION, &trusted, sizeof (trusted) },
- { CKA_TRUST_KEY_ENCIPHERMENT, &trusted, sizeof (trusted) },
- { CKA_TRUST_DATA_ENCIPHERMENT, &trusted, sizeof (trusted) },
- { CKA_TRUST_KEY_AGREEMENT, &trusted, sizeof (trusted) },
- { CKA_TRUST_KEY_CERT_SIGN, &trusted, sizeof (trusted) },
- { CKA_TRUST_CRL_SIGN, &trusted, sizeof (trusted) },
- { CKA_INVALID, }
- };
-
- CK_ATTRIBUTE server_anchor[] = {
- { CKA_LABEL, "Custom Label", 12 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE client_anchor[] = {
- { CKA_LABEL, "Custom Label", 12 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE email_distrust[] = {
- { CKA_LABEL, "Custom Label", 12 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
- { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) },
- { CKA_INVALID },
- };
-
CK_ATTRIBUTE *expected[] = {
- NULL,
+ cacert3,
eku_extension,
reject_extension,
- nss_trust,
- email_distrust,
- server_anchor,
- client_anchor
+ NULL
};
CK_ATTRIBUTE *cert;
CK_ATTRIBUTE *object;
- CK_BBOOL bval;
+ CK_OBJECT_HANDLE handle;
int ret;
int i;
setup (cu);
ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3-trusted.pem",
- P11_PARSE_FLAG_ANCHOR, on_parse_object, cu);
+ P11_PARSE_FLAG_ANCHOR);
CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
/*
* Should have gotten:
* - 1 certificate
* - 2 stapled extensions
- * - 1 trust object
- * - 3 trust assertions
*/
- CuAssertIntEquals (cu, 7, test.objects->num);
+ CuAssertIntEquals (cu, 3, p11_index_size (test.index));
/* The certificate */
- cert = test.objects->elem[0];
- test_check_cacert3_ca (cu, cert, NULL);
+ cert = parsed_attrs (certificate_match);
+ test_check_attrs (cu, expected[0], cert);
- if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &bval))
- CuFail (cu, "missing CKA_TRUSTED");
- CuAssertIntEquals (cu, CK_TRUE, bval);
+ /* The other objects */
+ for (i = 1; expected[i]; i++) {
+ handle = p11_index_findn (test.index, expected[i], 2);
+ CuAssertTrue (cu, handle != 0);
- if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &bval))
- CuFail (cu, "missing CKA_X_DISTRUSTED");
- CuAssertIntEquals (cu, CK_FALSE, bval);
+ object = p11_index_lookup (test.index, handle);
+ CuAssertPtrNotNull (cu, object);
- /* The other objects */
- for (i = 1; i < 7; i++) {
- object = test.objects->elem[i];
test_check_attrs (cu, expected[i], object);
test_check_id (cu, cert, object);
}
@@ -294,191 +233,41 @@ test_parse_openssl_trusted (CuTest *cu)
static void
test_parse_openssl_distrusted (CuTest *cu)
{
- CK_TRUST distrusted = CKT_NSS_NOT_TRUSTED;
- CK_OBJECT_CLASS certificate_extension = CKO_X_CERTIFICATE_EXTENSION;
- CK_OBJECT_CLASS trust_object = CKO_NSS_TRUST;
- CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
- CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION;
- CK_X_ASSERTION_TYPE distrusted_certificate = CKT_X_DISTRUSTED_CERTIFICATE;
- CK_CERTIFICATE_TYPE x509 = CKC_X_509;
- CK_ULONG category = 2; /* authority */
- CK_BBOOL vtrue = CK_TRUE;
- CK_BBOOL vfalse = CK_FALSE;
-
- CK_ATTRIBUTE certificate[] = {
- { CKA_CLASS, &klass, sizeof (klass), },
- { CKA_TOKEN, &vtrue, sizeof (vtrue) },
- { CKA_PRIVATE, &vfalse, sizeof (vfalse) },
- { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) },
- { CKA_CLASS, &klass, sizeof (klass) },
- { CKA_LABEL, "Red Hat Is the CA", 17 },
+ CK_ATTRIBUTE distrust_cert[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate), },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
{ CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
- { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) },
- { CKA_CHECK_VALUE, "\xe9z}", 3 },
- { CKA_START_DATE, "20090916", 8 },
- { CKA_END_DATE, "20190914", 8, },
- { CKA_SERIAL_NUMBER, "\x02\x01\x01", 3 },
- { CKA_TRUSTED, &vfalse, sizeof (vfalse) },
- { CKA_X_DISTRUSTED, &vtrue, sizeof (vtrue) },
+ { CKA_TRUSTED, &falsev, sizeof (falsev) },
+ { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
{ CKA_INVALID },
};
CK_ATTRIBUTE eku_extension[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
{ CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
{ CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE, sizeof (P11_OID_EXTENDED_KEY_USAGE) },
- { CKA_X_CRITICAL, &vtrue, sizeof (vtrue) },
+ { CKA_X_CRITICAL, &truev, sizeof (truev) },
{ CKA_VALUE, "\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x99\x77\x06\x0a\x10", 14 },
{ CKA_INVALID },
};
CK_ATTRIBUTE reject_extension[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
{ CKA_CLASS, &certificate_extension, sizeof (certificate_extension), },
{ CKA_OBJECT_ID, (void *)P11_OID_OPENSSL_REJECT, sizeof (P11_OID_OPENSSL_REJECT) },
- { CKA_X_CRITICAL, &vfalse, sizeof (vfalse) },
+ { CKA_X_CRITICAL, &falsev, sizeof (falsev) },
{ CKA_VALUE, "\x30\x0a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02", 12 },
{ CKA_INVALID },
};
- CK_ATTRIBUTE nss_trust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_object, sizeof (trust_object), },
- { CKA_CERT_SHA1_HASH, "\xe9z}\xe3\x82""7\xa0U\xb1k\xfe\xffo.\x03\x15*\xba\xb9\x90", 20 },
- { CKA_CERT_MD5_HASH, "\xda\xb4<\xe7;QK\x1a\xe5\xeau\xa1\xc9 \xdf""B", 16 },
- { CKA_SERIAL_NUMBER, "\x02\x01\x01", 3 },
- { CKA_TRUST_SERVER_AUTH, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_CLIENT_AUTH, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_EMAIL_PROTECTION, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_CODE_SIGNING, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_IPSEC_END_SYSTEM, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_IPSEC_TUNNEL, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_IPSEC_USER, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_TIME_STAMPING, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_DIGITAL_SIGNATURE, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_NON_REPUDIATION, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_KEY_ENCIPHERMENT, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_DATA_ENCIPHERMENT, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_KEY_AGREEMENT, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_KEY_CERT_SIGN, &distrusted, sizeof (distrusted) },
- { CKA_TRUST_CRL_SIGN, &distrusted, sizeof (distrusted) },
- { CKA_INVALID, }
- };
-
- unsigned char red_hat_issuer[] = {
- 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
- 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0e, 0x4e, 0x6f, 0x72, 0x74, 0x68,
- 0x20, 0x43, 0x61, 0x72, 0x6f, 0x6c, 0x69, 0x6e, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
- 0x04, 0x07, 0x13, 0x07, 0x52, 0x61, 0x6c, 0x65, 0x69, 0x67, 0x68, 0x31, 0x16, 0x30, 0x14, 0x06,
- 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x2c, 0x20, 0x49,
- 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x02, 0x49, 0x53,
- 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x52, 0x65, 0x64, 0x20, 0x48,
- 0x61, 0x74, 0x20, 0x49, 0x53, 0x20, 0x43, 0x41, 0x31, 0x26, 0x30, 0x24, 0x06, 0x09, 0x2a, 0x86,
- 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x17, 0x73, 0x79, 0x73, 0x61, 0x64, 0x6d, 0x69,
- 0x6e, 0x2d, 0x72, 0x64, 0x75, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d,
- };
-
- unsigned char red_hat_serial[] = {
- 0x02, 0x01, 0x01,
- };
-
- CK_ATTRIBUTE server_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE client_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE code_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, strlen (P11_OID_CODE_SIGNING_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE email_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE ipsec_system_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, strlen (P11_OID_IPSEC_END_SYSTEM_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE ipsec_tunnel_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, strlen (P11_OID_IPSEC_TUNNEL_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE ipsec_user_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, strlen (P11_OID_IPSEC_USER_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE stamping_distrust[] = {
- { CKA_LABEL, "Red Hat Is the CA", 17 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) },
- { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) },
- { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, strlen (P11_OID_TIME_STAMPING_STR) },
- { CKA_INVALID },
- };
-
CK_ATTRIBUTE *expected[] = {
- certificate,
+ distrust_cert,
eku_extension,
reject_extension,
- nss_trust,
- server_distrust,
- client_distrust,
- code_distrust,
- email_distrust,
- ipsec_system_distrust,
- ipsec_tunnel_distrust,
- ipsec_user_distrust,
- stamping_distrust,
+ NULL
};
CK_ATTRIBUTE *cert;
CK_ATTRIBUTE *object;
+ CK_OBJECT_HANDLE handle;
int ret;
int i;
@@ -489,22 +278,26 @@ test_parse_openssl_distrusted (CuTest *cu)
* so we parse this as an anchor, but expect it to be blacklisted
*/
ret = p11_parse_file (test.parser, SRCDIR "/files/distrusted.pem",
- P11_PARSE_FLAG_ANCHOR, on_parse_object, cu);
+ P11_PARSE_FLAG_ANCHOR);
CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
/*
* Should have gotten:
* - 1 certificate
* - 2 stapled extensions
- * - 1 trust object
- * - 8 trust assertions
*/
- CuAssertIntEquals (cu, 12, test.objects->num);
- cert = test.objects->elem[0];
+ CuAssertIntEquals (cu, 3, p11_index_size (test.index));
+ cert = parsed_attrs (certificate_match);
+ test_check_attrs (cu, expected[0], cert);
/* The other objects */
- for (i = 0; i < 12; i++) {
- object = test.objects->elem[i];
+ for (i = 1; expected[i]; i++) {
+ handle = p11_index_findn (test.index, expected[i], 2);
+ CuAssertTrue (cu, handle != 0);
+
+ object = p11_index_lookup (test.index, handle);
+ CuAssertPtrNotNull (cu, object);
+
test_check_attrs (cu, expected[i], object);
test_check_id (cu, cert, object);
}
@@ -513,246 +306,35 @@ test_parse_openssl_distrusted (CuTest *cu)
}
static void
-test_parse_with_key_usage (CuTest *cu)
-{
- CK_TRUST trusted = CKT_NSS_TRUSTED;
- CK_TRUST unknown = CKT_NSS_TRUST_UNKNOWN;
- CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
- CK_OBJECT_CLASS trust_object = CKO_NSS_TRUST;
- CK_BBOOL vtrue = CK_TRUE;
- CK_BBOOL vfalse = CK_FALSE;
- CK_CERTIFICATE_TYPE x509 = CKC_X_509;
- CK_ULONG category = 3; /* other entity */
-
- CK_ATTRIBUTE certificate[] = {
- { CKA_CLASS, &klass, sizeof (klass), },
- { CKA_TOKEN, &vtrue, sizeof (vtrue) },
- { CKA_PRIVATE, &vfalse, sizeof (vfalse) },
- { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) },
- { CKA_CLASS, &klass, sizeof (klass) },
- { CKA_LABEL, "self-signed-with-ku.example.com", 31 },
- { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
- { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) },
- { CKA_CHECK_VALUE, "d/\x9c", 3 },
- { CKA_START_DATE, "20121211", 8 },
- { CKA_END_DATE, "20130110", 8, },
- { CKA_ISSUER, "0*1(0&\x06\x03U\x04\x03\x13\x1f""self-signed-with-ku.example.com", 44 },
- { CKA_SUBJECT, "0*1(0&\x06\x03U\x04\x03\x13\x1f""self-signed-with-ku.example.com", 44 },
- { CKA_SERIAL_NUMBER, "\x02\x02\x03x", 4 },
- { CKA_TRUSTED, &vtrue, sizeof (vtrue) },
- { CKA_X_DISTRUSTED, &vfalse, sizeof (vfalse) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE nss_trust[] = {
- { CKA_LABEL, "self-signed-with-ku.example.com", 31 },
- { CKA_CLASS, &trust_object, sizeof (trust_object), },
- { CKA_CERT_SHA1_HASH, "d/\x9c=\xbc\x9a\x7f\x91\xc7wT\t`\x86\xe2\x8e\x8f\xa8J\x12", 20 },
- { CKA_CERT_MD5_HASH, "\xb1N=\x16\x12?dz\x97\x81""By/\xcc\x97\x82", 16 },
- { CKA_ISSUER, "0*1(0&\x06\x03U\x04\x03\x13\x1f""self-signed-with-ku.example.com", 44 },
- { CKA_SUBJECT, "0*1(0&\x06\x03U\x04\x03\x13\x1f""self-signed-with-ku.example.com", 44 },
- { CKA_SERIAL_NUMBER, "\x02\x02\x03x", 4 },
- { CKA_TRUST_SERVER_AUTH, &trusted, sizeof (trusted) },
- { CKA_TRUST_CLIENT_AUTH, &trusted, sizeof (trusted) },
- { CKA_TRUST_EMAIL_PROTECTION, &trusted, sizeof (trusted) },
- { CKA_TRUST_CODE_SIGNING, &trusted, sizeof (trusted) },
- { CKA_TRUST_IPSEC_END_SYSTEM, &trusted, sizeof (trusted) },
- { CKA_TRUST_IPSEC_TUNNEL, &trusted, sizeof (trusted) },
- { CKA_TRUST_IPSEC_USER, &trusted, sizeof (trusted) },
- { CKA_TRUST_TIME_STAMPING, &trusted, sizeof (trusted) },
- { CKA_TRUST_DIGITAL_SIGNATURE, &trusted, sizeof (trusted) },
- { CKA_TRUST_NON_REPUDIATION, &unknown, sizeof (unknown) },
- { CKA_TRUST_KEY_ENCIPHERMENT, &unknown, sizeof (unknown) },
- { CKA_TRUST_DATA_ENCIPHERMENT, &unknown, sizeof (unknown) },
- { CKA_TRUST_KEY_AGREEMENT, &unknown, sizeof (unknown) },
- { CKA_TRUST_KEY_CERT_SIGN, &trusted, sizeof (trusted) },
- { CKA_TRUST_CRL_SIGN, &unknown, sizeof (unknown) },
- { CKA_INVALID, }
- };
-
- CK_ATTRIBUTE *cert;
- CK_ATTRIBUTE *object;
- CK_BBOOL bval;
- int ret;
-
- setup (cu);
-
- ret = p11_parse_file (test.parser, SRCDIR "/files/self-signed-with-ku.der",
- P11_PARSE_FLAG_ANCHOR, on_parse_object, cu);
- CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
-
- /* Should have gotten certificate, and a trust object */
- CuAssertIntEquals (cu, 2, test.objects->num);
-
- cert = test.objects->elem[0];
- test_check_attrs (cu, certificate, cert);
-
- if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &bval))
- CuFail (cu, "missing CKA_TRUSTED");
- CuAssertIntEquals (cu, CK_TRUE, bval);
-
- if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &bval))
- CuFail (cu, "missing CKA_X_DISTRUSTED");
- CuAssertIntEquals (cu, CK_FALSE, bval);
-
- object = test.objects->elem[1];
- test_check_attrs (cu, nss_trust, object);
- test_check_id (cu, cert, object);
-
- teardown (cu);
-}
-
-static void
test_parse_anchor (CuTest *cu)
{
- CK_BBOOL vtrue = CK_TRUE;
- CK_OBJECT_CLASS trust_object = CKO_NSS_TRUST;
- CK_ATTRIBUTE trusted = { CKA_TRUSTED, &vtrue, sizeof (vtrue) };
- CK_TRUST delegator = CKT_NSS_TRUSTED_DELEGATOR;
- CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION;
- CK_X_ASSERTION_TYPE anchored_certificate = CKT_X_ANCHORED_CERTIFICATE;
-
- CK_ATTRIBUTE nss_trust[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_object, sizeof (trust_object), },
- { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
- { CKA_CERT_MD5_HASH, "\xf7\x25\x12\x82\x4e\x67\xb5\xd0\x8d\x92\xb7\x7c\x0b\x86\x7a\x42", 16 },
- { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
- { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
- { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
- { CKA_TRUST_SERVER_AUTH, &delegator, sizeof (delegator) },
- { CKA_TRUST_CLIENT_AUTH, &delegator, sizeof (delegator) },
- { CKA_TRUST_EMAIL_PROTECTION, &delegator, sizeof (delegator) },
- { CKA_TRUST_CODE_SIGNING, &delegator, sizeof (delegator) },
- { CKA_TRUST_IPSEC_END_SYSTEM, &delegator, sizeof (delegator) },
- { CKA_TRUST_IPSEC_TUNNEL, &delegator, sizeof (delegator) },
- { CKA_TRUST_IPSEC_USER, &delegator, sizeof (delegator) },
- { CKA_TRUST_TIME_STAMPING, &delegator, sizeof (delegator) },
- { CKA_TRUST_DIGITAL_SIGNATURE, &delegator, sizeof (delegator) },
- { CKA_TRUST_NON_REPUDIATION, &delegator, sizeof (delegator) },
- { CKA_TRUST_KEY_ENCIPHERMENT, &delegator, sizeof (delegator) },
- { CKA_TRUST_DATA_ENCIPHERMENT, &delegator, sizeof (delegator) },
- { CKA_TRUST_KEY_AGREEMENT, &delegator, sizeof (delegator) },
- { CKA_TRUST_KEY_CERT_SIGN, &delegator, sizeof (delegator) },
- { CKA_TRUST_CRL_SIGN, &delegator, sizeof (delegator) },
- { CKA_INVALID, }
- };
-
- CK_ATTRIBUTE server_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE client_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE code_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, strlen (P11_OID_CODE_SIGNING_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE email_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE ipsec_system_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, strlen (P11_OID_IPSEC_END_SYSTEM_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE ipsec_tunnel_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, strlen (P11_OID_IPSEC_TUNNEL_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE ipsec_user_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
- { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, strlen (P11_OID_IPSEC_USER_STR) },
- { CKA_INVALID },
- };
-
- CK_ATTRIBUTE stamping_anchor[] = {
- { CKA_LABEL, "CAcert Class 3 Root", 19 },
- { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+ CK_ATTRIBUTE cacert3[] = {
+ { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+ { CKA_CLASS, &certificate, sizeof (certificate) },
{ CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
- { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) },
- { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, strlen (P11_OID_TIME_STAMPING_STR) },
+ { CKA_MODIFIABLE, &falsev, sizeof (falsev) },
+ { CKA_TRUSTED, &truev, sizeof (truev) },
+ { CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
{ CKA_INVALID },
};
- CK_ATTRIBUTE *expected[] = {
- NULL,
- nss_trust,
- server_anchor,
- client_anchor,
- code_anchor,
- email_anchor,
- ipsec_system_anchor,
- ipsec_tunnel_anchor,
- ipsec_user_anchor,
- stamping_anchor,
- };
-
CK_ATTRIBUTE *cert;
- CK_ATTRIBUTE *object;
- CK_ATTRIBUTE *attr;
int ret;
- int i;
setup (cu);
ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
- P11_PARSE_FLAG_ANCHOR, on_parse_object, cu);
+ P11_PARSE_FLAG_ANCHOR);
CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
/*
* Should have gotten:
* - 1 certificate
- * - 1 trust object
- * - 8 trust assertions
*/
- CuAssertIntEquals (cu, 10, test.objects->num);
-
- cert = test.objects->elem[0];
- test_check_cacert3_ca (cu, cert, NULL);
- attr = p11_attrs_find (cert, CKA_TRUSTED);
- test_check_attr (cu, &trusted, attr);
+ CuAssertIntEquals (cu, 1, p11_index_size (test.index));
- for (i = 1; i < 10; i++) {
- object = test.objects->elem[i];
- test_check_attrs (cu, expected[i], object);
- test_check_id (cu, cert, object);
- }
+ cert = parsed_attrs (certificate_match);
+ test_check_attrs (cu, cacert3, cert);
teardown (cu);
}
@@ -760,29 +342,20 @@ test_parse_anchor (CuTest *cu)
/* TODO: A certificate that uses generalTime needs testing */
static void
-test_parse_no_sink (CuTest *cu)
-{
- int ret;
-
- setup (cu);
-
- ret = p11_parse_file (test.parser, SRCDIR "/files/cacert3.der",
- 0, NULL, NULL);
- CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret);
-
- teardown (cu);
-}
-
-static void
test_parse_invalid_file (CuTest *cu)
{
int ret;
setup (cu);
- ret = p11_parse_file (test.parser, "/nonexistant", 0, on_parse_object, cu);
+ p11_message_quiet ();
+
+ ret = p11_parse_file (test.parser, "/nonexistant",
+ P11_PARSE_FLAG_NONE);
CuAssertIntEquals (cu, P11_PARSE_FAILURE, ret);
+ p11_message_loud ();
+
teardown (cu);
}
@@ -793,10 +366,14 @@ test_parse_unrecognized (CuTest *cu)
setup (cu);
+ p11_message_quiet ();
+
ret = p11_parse_file (test.parser, SRCDIR "/files/unrecognized-file.txt",
- 0, on_parse_object, cu);
+ P11_PARSE_FLAG_NONE);
CuAssertIntEquals (cu, P11_PARSE_UNRECOGNIZED, ret);
+ p11_message_loud ();
+
teardown (cu);
}
@@ -810,15 +387,12 @@ main (void)
putenv ("P11_KIT_STRICT=1");
p11_library_init ();
p11_debug_init ();
- p11_message_quiet ();
SUITE_ADD_TEST (suite, test_parse_der_certificate);
SUITE_ADD_TEST (suite, test_parse_pem_certificate);
SUITE_ADD_TEST (suite, test_parse_openssl_trusted);
SUITE_ADD_TEST (suite, test_parse_openssl_distrusted);
- SUITE_ADD_TEST (suite, test_parse_with_key_usage);
SUITE_ADD_TEST (suite, test_parse_anchor);
- SUITE_ADD_TEST (suite, test_parse_no_sink);
SUITE_ADD_TEST (suite, test_parse_invalid_file);
SUITE_ADD_TEST (suite, test_parse_unrecognized);
diff --git a/trust/tests/test-token.c b/trust/tests/test-token.c
index ad25da0..5cca233 100644
--- a/trust/tests/test-token.c
+++ b/trust/tests/test-token.c
@@ -83,33 +83,10 @@ test_token_load (CuTest *cu)
teardown (cu);
}
-static bool
-check_object (CK_ATTRIBUTE *match)
-{
- CK_OBJECT_HANDLE *handles;
- CK_ATTRIBUTE *attrs;
- p11_index *index;
- bool ret = false;
- int i;
-
- index = p11_token_index (test.token);
- handles = p11_index_snapshot (index, NULL, match, p11_attrs_count (match));
-
- for (i = 0; handles[i] != 0; i++) {
- attrs = p11_index_lookup (index, handles[i]);
- if (p11_attrs_match (attrs, match)) {
- ret = true;
- break;
- }
- }
-
- free (handles);
- return ret;
-}
-
static void
test_token_flags (CuTest *cu)
{
+ CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
CK_BBOOL falsev = CK_FALSE;
CK_BBOOL truev = CK_TRUE;
@@ -120,6 +97,7 @@ test_token_flags (CuTest *cu)
*/
CK_ATTRIBUTE blacklist[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
{ CKA_LABEL, "Red Hat Is the CA", 17 },
{ CKA_SERIAL_NUMBER, "\x02\x01\x01", 3 },
{ CKA_TRUSTED, &falsev, sizeof (falsev) },
@@ -142,6 +120,7 @@ test_token_flags (CuTest *cu)
};
CK_ATTRIBUTE blacklist2[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
{ CKA_SUBJECT, (void *)self_server_subject, sizeof (self_server_subject) },
{ CKA_TRUSTED, &falsev, sizeof (falsev) },
{ CKA_X_DISTRUSTED, &truev, sizeof (truev) },
@@ -155,6 +134,7 @@ test_token_flags (CuTest *cu)
*/
CK_ATTRIBUTE anchor[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
{ CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
{ CKA_TRUSTED, &truev, sizeof (truev) },
{ CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
@@ -179,27 +159,40 @@ test_token_flags (CuTest *cu)
*/
CK_ATTRIBUTE notrust[] = {
+ { CKA_CLASS, &certificate, sizeof (certificate) },
{ CKA_SUBJECT, (void *)cacert_root_subject, sizeof (cacert_root_subject) },
{ CKA_TRUSTED, &falsev, sizeof (falsev) },
{ CKA_X_DISTRUSTED, &falsev, sizeof (falsev) },
{ CKA_INVALID },
};
- CK_ATTRIBUTE invalid[] = {
- { CKA_LABEL, "Waonec9aoe9", 8 },
- { CKA_INVALID },
+ CK_ATTRIBUTE *expected[] = {
+ anchor,
+ blacklist,
+ blacklist2,
+ notrust,
+ NULL,
};
+ CK_OBJECT_HANDLE handle;
+ CK_ATTRIBUTE *object;
+ int i;
+
setup (cu, SRCDIR "/input");
if (p11_token_load (test.token) < 0)
CuFail (cu, "should not be reached");
- CuAssertTrue (cu, !check_object (invalid));
- CuAssertTrue (cu, check_object (anchor));
- CuAssertTrue (cu, check_object (blacklist));
- CuAssertTrue (cu, check_object (blacklist2));
- CuAssertTrue (cu, check_object (notrust));
+ /* The other objects */
+ for (i = 0; expected[i]; i++) {
+ handle = p11_index_findn (p11_token_index (test.token), expected[i], 2);
+ CuAssertTrue (cu, handle != 0);
+
+ object = p11_index_lookup (p11_token_index (test.token), handle);
+ CuAssertPtrNotNull (cu, object);
+
+ test_check_attrs (cu, expected[i], object);
+ }
teardown (cu);
}
@@ -234,7 +227,6 @@ main (void)
putenv ("P11_KIT_STRICT=1");
p11_library_init ();
p11_debug_init ();
- p11_message_quiet ();
SUITE_ADD_TEST (suite, test_token_load);
SUITE_ADD_TEST (suite, test_token_flags);
diff --git a/trust/token.c b/trust/token.c
index 558f374..ae140c7 100644
--- a/trust/token.c
+++ b/trust/token.c
@@ -34,7 +34,9 @@
#include "config.h"
+#include "asn1.h"
#include "attrs.h"
+#include "builder.h"
#include "compat.h"
#define P11_DEBUG_FLAG P11_DEBUG_TRUST
#include "debug.h"
@@ -59,6 +61,7 @@
struct _p11_token {
p11_parser *parser;
p11_index *index;
+ p11_builder *builder;
const char *path;
CK_SLOT_ID slot;
int loaded;
@@ -84,8 +87,7 @@ loader_load_file (p11_token *token,
{
int ret;
- ret = p11_parse_file (token->parser, filename, flags,
- on_parser_object, token);
+ ret = p11_parse_file (token->parser, filename, flags);
switch (ret) {
case P11_PARSE_SUCCESS:
@@ -361,12 +363,14 @@ load_builtin_objects (p11_token *token)
{ CKA_TRUST_STEP_UP_APPROVED, &vfalse, sizeof (vfalse) },
};
+ p11_index_batch (token->index);
on_parser_object (p11_attrs_buildn (NULL, builtin_root_list, ELEMS (builtin_root_list)), token);
on_parser_object (p11_attrs_buildn (NULL, distrust_trustwave1, ELEMS (distrust_trustwave1)), token);
on_parser_object (p11_attrs_buildn (NULL, distrust_trustwave2, ELEMS (distrust_trustwave2)), token);
on_parser_object (p11_attrs_buildn (NULL, distrust_turktrust1, ELEMS (distrust_turktrust1)), token);
on_parser_object (p11_attrs_buildn (NULL, distrust_turktrust2, ELEMS (distrust_turktrust2)), token);
on_parser_object (p11_attrs_buildn (NULL, distrust_p11subca, ELEMS (distrust_p11subca)), token);
+ p11_index_finish (token->index);
return 1;
}
@@ -396,6 +400,7 @@ p11_token_free (p11_token *token)
p11_index_free (token->index);
p11_parser_free (token->parser);
+ p11_builder_free (token->builder);
free (token);
}
@@ -408,12 +413,18 @@ p11_token_new (CK_SLOT_ID slot,
token = calloc (1, sizeof (p11_token));
return_val_if_fail (token != NULL, NULL);
- token->parser = p11_parser_new ();
- return_val_if_fail (token->parser != NULL, NULL);
+ token->builder = p11_builder_new (P11_BUILDER_FLAG_TOKEN);
+ return_val_if_fail (token->builder != NULL, NULL);
- token->index = p11_index_new (NULL, NULL, NULL);
+ token->index = p11_index_new (p11_builder_build,
+ p11_builder_changed,
+ token->builder);
return_val_if_fail (token->index != NULL, NULL);
+ token->parser = p11_parser_new (token->index,
+ p11_builder_get_cache (token->builder));
+ return_val_if_fail (token->parser != NULL, NULL);
+
token->path = strdup (path);
return_val_if_fail (token->path != NULL, NULL);