[gnome-keyring/trust-store] [xdg-store] Tests and more bug fixes for trust assertions.



commit 4c31c175231c906b73e958a0856adc1df0e98252
Author: Stef Walter <stefw collabora co uk>
Date:   Fri Nov 26 19:38:20 2010 +0000

    [xdg-store] Tests and more bug fixes for trust assertions.
    
     * Start of netscape trust map tests.
     * Rewrite how netscape trust attribute mapping happens.
     * Change how assertions are put into trust hash table.

 pkcs11/xdg-store/gkm-xdg-assertion.c    |   17 +-
 pkcs11/xdg-store/gkm-xdg-module.c       |    6 +-
 pkcs11/xdg-store/gkm-xdg-trust.c        |  273 +++++++++---------
 pkcs11/xdg-store/tests/test-xdg-trust.c |  494 +++++++++++++++++++++++--------
 4 files changed, 516 insertions(+), 274 deletions(-)
---
diff --git a/pkcs11/xdg-store/gkm-xdg-assertion.c b/pkcs11/xdg-store/gkm-xdg-assertion.c
index 3755c73..33b024e 100644
--- a/pkcs11/xdg-store/gkm-xdg-assertion.c
+++ b/pkcs11/xdg-store/gkm-xdg-assertion.c
@@ -90,7 +90,7 @@ lookup_or_create_trust_object (GkmSession *session, GkmManager *manager,
 		/* Attributes used for looking up trust object */
 		memcpy (lookups + 1, issuer, sizeof (*issuer));
 		memcpy (lookups + 2, serial, sizeof (*serial));
-		n_lookups = 2;
+		n_lookups = 3;
 		break;
 
 	default:
@@ -178,20 +178,21 @@ factory_create_assertion (GkmSession *session, GkmTransaction *transaction,
 	/* Add the assertion to the trust object */
 	if (!gkm_transaction_get_failed (transaction)) {
 		previous = gkm_xdg_trust_add_assertion (trust, GKM_ASSERTION (assertion), transaction);
-		if (previous == NULL) {
+		if (gkm_transaction_get_failed (transaction)) {
 			gkm_transaction_fail (transaction, CKR_GENERAL_ERROR);
 
 		/* If trust refused to add this object, return whatever we did add */
 		} else if (previous != assertion) {
+			g_assert (previous);
 			g_object_unref (assertion);
 			assertion = g_object_ref (previous);
-		}
-	}
 
-	if (!gkm_transaction_get_failed (transaction)) {
-		gkm_attributes_consume (attrs, n_attrs, CKA_G_ASSERTION_TYPE, CKA_G_PURPOSE, G_MAXULONG);
-		gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (assertion),
-		                                      TRUE, attrs, n_attrs);
+		/* A new trust assertion */
+		} else {
+			gkm_attributes_consume (attrs, n_attrs, CKA_G_ASSERTION_TYPE, CKA_G_PURPOSE, G_MAXULONG);
+			gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (assertion),
+			                                      TRUE, attrs, n_attrs);
+		}
 	}
 
 	g_object_unref (trust);
diff --git a/pkcs11/xdg-store/gkm-xdg-module.c b/pkcs11/xdg-store/gkm-xdg-module.c
index bae8abd..1f5ef01 100644
--- a/pkcs11/xdg-store/gkm-xdg-module.c
+++ b/pkcs11/xdg-store/gkm-xdg-module.c
@@ -374,11 +374,11 @@ static void
 gkm_xdg_module_real_add_token_object (GkmModule *module, GkmTransaction *transaction,
                                       GkmObject *object)
 {
+	gchar *filename = NULL;
 	GkmXdgModule *self;
 	GkmTrust *trust;
 	gchar *basename;
 	gchar *actual;
-	gchar *filename;
 
 	self = GKM_XDG_MODULE (module);
 
@@ -386,6 +386,10 @@ gkm_xdg_module_real_add_token_object (GkmModule *module, GkmTransaction *transac
 	if (GKM_XDG_IS_ASSERTION (object)) {
 		trust = gkm_assertion_get_trust_object (GKM_ASSERTION (object));
 		object = GKM_OBJECT (trust);
+
+		/* If this trust object has already been added, then ignore */
+		if (lookup_filename_for_object (object))
+			return;
 	}
 
 	/* Double check that the object is in fact serializable */
diff --git a/pkcs11/xdg-store/gkm-xdg-trust.c b/pkcs11/xdg-store/gkm-xdg-trust.c
index 80c532f..df3f8a8 100644
--- a/pkcs11/xdg-store/gkm-xdg-trust.c
+++ b/pkcs11/xdg-store/gkm-xdg-trust.c
@@ -43,24 +43,11 @@
 
 #include <glib/gi18n.h>
 
-/* COMPAT: netscape's usages */
-typedef struct _NetscapeFlags {
-	CK_ULONG server_auth;
-	CK_ULONG client_auth;
-	CK_ULONG code_signing;
-	CK_ULONG email_protection;
-	CK_ULONG ipsec_end_system;
-	CK_ULONG ipsec_tunnel;
-	CK_ULONG ipsec_user;
-	CK_ULONG time_stamping;
-} NetscapeFlags;
-
 struct _GkmXdgTrustPrivate {
-	GNode *asn;
 	GHashTable *assertions;
+	GNode *asn;
 	gpointer data;
 	gsize n_data;
-	NetscapeFlags netscape;
 };
 
 /* From asn1-def-xdg.c */
@@ -124,15 +111,13 @@ trust_get_der (GkmXdgTrust *self, const gchar *part, CK_ATTRIBUTE_PTR attr)
 	g_assert (GKM_XDG_IS_TRUST (self));
 
 	node = egg_asn1x_node (self->pv->asn, "reference", "certReference", part, NULL);
+	g_return_val_if_fail (node, CKR_GENERAL_ERROR);
 
 	/* If the assertion doesn't contain this info ... */
-	if (node == NULL)
+	if (!egg_asn1x_have (node))
 		return CKR_ATTRIBUTE_TYPE_INVALID;
 
 	element = egg_asn1x_get_raw_element (node, &n_element);
-	if (element == NULL)
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-
 	return gkm_attribute_set_data (attr, element, n_element);
 }
 
@@ -147,12 +132,15 @@ trust_get_integer (GkmXdgTrust *self, const gchar *part, CK_ATTRIBUTE_PTR attr)
 	g_assert (GKM_XDG_IS_TRUST (self));
 
 	node = egg_asn1x_node (self->pv->asn, "reference", "certReference", part, NULL);
+	g_return_val_if_fail (node, CKR_GENERAL_ERROR);
 
 	/* If the assertion doesn't contain this info ... */
-	if (node == NULL)
+	if (!egg_asn1x_have (node))
 		return CKR_ATTRIBUTE_TYPE_INVALID;
 
 	integer = egg_asn1x_get_integer_as_raw (node, NULL, &n_integer);
+	g_return_val_if_fail (integer, CKR_GENERAL_ERROR);
+
 	rv = gkm_attribute_set_data (attr, integer, n_integer);
 	g_free (integer);
 
@@ -167,9 +155,10 @@ trust_get_hash (GkmXdgTrust *self, GChecksumType ctype, CK_ATTRIBUTE_PTR attr)
 	gsize n_element;
 
 	cert = egg_asn1x_node (self->pv->asn, "reference", "certComplete", NULL);
+	g_return_val_if_fail (cert, CKR_GENERAL_ERROR);
 
 	/* If it's not stored, then this attribute is not present */
-	if (cert == NULL)
+	if (!egg_asn1x_have (cert))
 		return CKR_ATTRIBUTE_TYPE_INVALID;
 
 	element = egg_asn1x_get_raw_element (cert, &n_element);
@@ -178,6 +167,27 @@ trust_get_hash (GkmXdgTrust *self, GChecksumType ctype, CK_ATTRIBUTE_PTR attr)
 	return gkm_attribute_set_checksum (attr, ctype, element, n_element);
 }
 
+static CK_RV
+trust_get_complete (GkmXdgTrust *self, CK_ATTRIBUTE_PTR attr)
+{
+	GNode *cert;
+	gconstpointer element;
+	gsize n_element;
+
+	cert = egg_asn1x_node (self->pv->asn, "reference", "certComplete", NULL);
+	g_return_val_if_fail (cert, CKR_GENERAL_ERROR);
+
+	/* If it's not stored, then this attribute is not present */
+	if (!egg_asn1x_have (cert))
+		return CKR_ATTRIBUTE_TYPE_INVALID;
+
+	element = egg_asn1x_get_raw_element (cert, &n_element);
+	g_return_val_if_fail (element, CKR_GENERAL_ERROR);
+
+	return gkm_attribute_set_data (attr, element, n_element);
+}
+
+
 static gboolean
 validate_der (CK_ATTRIBUTE_PTR attr, const gchar *asn_type)
 {
@@ -216,7 +226,7 @@ assertion_type_to_level_enum (CK_ASSERTION_TYPE type)
 		return TRUST_UNTRUSTED;
 	case CKT_G_CERTIFICATE_TRUST_ANCHOR:
 		return TRUST_TRUSTED_ANCHOR;
-	case CKT_NETSCAPE_TRUSTED:
+	case CKT_G_CERTIFICATE_TRUST_EXCEPTION:
 		return TRUST_TRUSTED;
 	default:
 		return 0;
@@ -240,53 +250,6 @@ level_enum_to_assertion_type (GQuark level, CK_ASSERTION_TYPE *type)
 }
 
 static void
-init_netscape_trust (NetscapeFlags *netscape)
-{
-	netscape->server_auth = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->client_auth = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->code_signing = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->email_protection = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->ipsec_end_system = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->ipsec_tunnel = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->ipsec_user = CKT_NETSCAPE_TRUST_UNKNOWN;
-	netscape->time_stamping = CKT_NETSCAPE_TRUST_UNKNOWN;
-}
-
-static void
-parse_netscape_trust (NetscapeFlags *netscape, GQuark level, const gchar *purpose)
-{
-	CK_TRUST trust;
-
-	if (level == TRUST_UNTRUSTED)
-		trust = CKT_NETSCAPE_TRUSTED;
-	else if (level == TRUST_TRUSTED_ANCHOR)
-		trust = CKT_NETSCAPE_TRUSTED_DELEGATOR;
-	else if (level == TRUST_TRUSTED)
-		trust = CKT_NETSCAPE_TRUSTED;
-	else if (level == TRUST_UNKNOWN)
-		trust = CKT_NETSCAPE_TRUST_UNKNOWN;
-	else
-		return;
-
-	if (g_str_equal (purpose, GKM_OID_EXTUSAGE_SERVER_AUTH))
-		netscape->server_auth = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_CLIENT_AUTH))
-		netscape->client_auth = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_CODE_SIGNING))
-		netscape->code_signing = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_EMAIL))
-		netscape->email_protection = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_IPSEC_ENDPOINT))
-		netscape->ipsec_end_system = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_IPSEC_TUNNEL))
-		netscape->ipsec_tunnel = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_IPSEC_USER))
-		netscape->ipsec_user = trust;
-	else if (g_str_equal (purpose, GKM_OID_EXTUSAGE_TIME_STAMPING))
-		netscape->time_stamping = trust;
-}
-
-static void
 check_and_unref_assertion (gpointer data)
 {
 	g_assert (GKM_IS_ASSERTION (data));
@@ -304,7 +267,7 @@ create_assertions (void)
 }
 
 static GkmAssertion*
-create_assertion (GkmXdgTrust *self, GNode *asn, NetscapeFlags *netscape)
+create_assertion (GkmXdgTrust *self, GNode *asn)
 {
 	CK_ASSERTION_TYPE type;
 	GkmAssertion *assertion;
@@ -315,8 +278,7 @@ create_assertion (GkmXdgTrust *self, GNode *asn, NetscapeFlags *netscape)
 
 	/* Get the trust level */
 	level = egg_asn1x_get_enumerated (egg_asn1x_node (asn, "level", NULL));
-	if (level == 0)
-		g_return_val_if_reached (NULL);
+	g_return_val_if_fail (level != 0, NULL);
 	if (!level_enum_to_assertion_type (level, &type))
 		g_message ("unsupported trust level %s in trust object", g_quark_to_string (level));
 	else if (type == 0)
@@ -335,22 +297,28 @@ create_assertion (GkmXdgTrust *self, GNode *asn, NetscapeFlags *netscape)
 
 	assertion = gkm_assertion_new (GKM_TRUST (self), type, purpose, peer);
 
-	/* Parse netscape trust flags */
-	if (peer == NULL)
-		parse_netscape_trust (netscape, level, purpose);
-
 	g_free (purpose);
 	g_free (peer);
 
 	return assertion;
 }
 
-static void
-stash_assertion_key (GkmAssertion *assertion, GByteArray *key)
+static GByteArray*
+create_assertion_key (const gchar *purpose, const gchar *peer)
 {
-	g_assert (g_object_get_qdata (G_OBJECT (assertion), QDATA_ASSERTION_KEY) == NULL);
-	g_object_set_qdata_full (G_OBJECT (assertion), QDATA_ASSERTION_KEY,
-	                         g_byte_array_ref (key), (GDestroyNotify)g_byte_array_unref);
+	GByteArray *key;
+
+	g_return_val_if_fail (purpose, NULL);
+
+	key = g_byte_array_new ();
+	g_byte_array_append (key, (void*)purpose, strlen (purpose));
+
+	if (peer != NULL) {
+		g_byte_array_append (key, (void*)"\0", 1);
+		g_byte_array_append (key, (void*)peer, strlen (peer));
+	}
+
+	return key;
 }
 
 static GByteArray*
@@ -359,6 +327,22 @@ lookup_assertion_key (GkmAssertion *assertion)
 	return g_object_get_qdata (G_OBJECT (assertion), QDATA_ASSERTION_KEY);
 }
 
+static GByteArray*
+lookup_or_create_assertion_key (GkmAssertion *assertion)
+{
+	GByteArray *key;
+
+	key = lookup_assertion_key (assertion);
+	if (key == NULL) {
+		key = create_assertion_key (gkm_assertion_get_purpose (assertion),
+		                            gkm_assertion_get_peer (assertion));
+		g_object_set_qdata_full (G_OBJECT (assertion), QDATA_ASSERTION_KEY,
+		                         g_byte_array_ref (key), (GDestroyNotify)g_byte_array_unref);
+	}
+
+	return key;
+}
+
 static gboolean
 complete_add_assertion (GkmTransaction *transaction, GObject *object, gpointer user_data)
 {
@@ -378,7 +362,7 @@ add_assertion_to_trust (GkmXdgTrust *self, GkmAssertion *assertion,
 {
 	GByteArray *key;
 
-	key = lookup_assertion_key (assertion);
+	key = lookup_or_create_assertion_key (assertion);
 	g_assert (key);
 
 	g_hash_table_insert (self->pv->assertions, g_byte_array_ref (key), g_object_ref (assertion));
@@ -430,7 +414,6 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 	gconstpointer element;
 	GHashTable *assertions;
 	GkmAssertion *assertion;
-	NetscapeFlags netscape;
 	gsize n_element;
 	GByteArray *key;
 	GNode *node;
@@ -441,7 +424,6 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 
 	assertions = self->pv->assertions;
 	self->pv->assertions = create_assertions ();
-	init_netscape_trust (&netscape);
 
 	count = egg_asn1x_count (egg_asn1x_node (asn, "assertions", NULL));
 
@@ -465,8 +447,7 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 
 		/* Create a new assertion */
 		} else {
-			assertion = create_assertion (self, node, &netscape);
-			stash_assertion_key (assertion, key);
+			assertion = create_assertion (self, node);
 		}
 
 		add_assertion_to_trust (self, assertion, NULL);
@@ -477,7 +458,6 @@ load_assertions (GkmXdgTrust *self, GNode *asn)
 	/* Override the stored assertions and netscape trust */
 	g_hash_table_remove_all (assertions);
 	g_hash_table_unref (assertions);
-	memcpy (&self->pv->netscape, &netscape, sizeof (netscape));
 
 	return TRUE;
 }
@@ -515,7 +495,7 @@ save_assertions (GkmXdgTrust *self, GNode *asn)
 	g_assert (GKM_XDG_IS_TRUST (self));
 	g_assert (asn);
 
-	node = egg_asn1x_node (asn, "trusts", NULL);
+	node = egg_asn1x_node (asn, "assertions", NULL);
 	egg_asn1x_clear (node);
 
 	g_hash_table_iter_init (&iter, self->pv->assertions);
@@ -533,42 +513,63 @@ create_trust_for_reference (GkmModule *module, GkmManager *manager,
                             CK_ATTRIBUTE_PTR serial, CK_ATTRIBUTE_PTR issuer)
 {
 	GkmXdgTrust *trust;
-	GNode *asn;
+	GNode *asn, *ref, *node;
 
 	asn = egg_asn1x_create (xdg_asn1_tab, "trust-1");
 	g_return_val_if_fail (asn, NULL);
 
-	egg_asn1x_set_integer_as_raw (egg_asn1x_node (asn, "reference", "certReference", "serialNumber", NULL),
+	ref = egg_asn1x_node (asn, "reference", NULL);
+	node = egg_asn1x_node (ref, "certReference", NULL);
+
+	egg_asn1x_set_choice (ref, node);
+	egg_asn1x_set_integer_as_raw (egg_asn1x_node (node, "serialNumber", NULL),
 	                              g_memdup (serial->pValue, serial->ulValueLen),
 	                              serial->ulValueLen, g_free);
 
-	egg_asn1x_set_raw_element (egg_asn1x_node (asn, "reference", "certReference", "issuer", NULL),
+	egg_asn1x_set_raw_element (egg_asn1x_node (node, "issuer", NULL),
 	                           g_memdup (issuer->pValue, issuer->ulValueLen),
 	                           issuer->ulValueLen, g_free);
 
 	trust = g_object_new (GKM_XDG_TYPE_TRUST, "module", module, "manager", manager, NULL);
 	trust->pv->asn = asn;
 
+	/* Encode it, so we have read access to all the data */
+	trust->pv->data = egg_asn1x_encode (asn, NULL, &trust->pv->n_data);
+	if (!trust->pv->data) {
+		g_warning ("created invalid trust object: %s", egg_asn1x_message (asn));
+		return NULL;
+	}
+
 	return trust;
 }
 
 static GkmXdgTrust*
-create_trust_for_certificate (GkmModule *module, GkmManager *manager,
+create_trust_for_complete (GkmModule *module, GkmManager *manager,
                               CK_ATTRIBUTE_PTR cert)
 {
 	GkmXdgTrust *trust;
-	GNode *asn;
+	GNode *asn, *ref, *node;
 
 	asn = egg_asn1x_create (xdg_asn1_tab, "trust-1");
 	g_return_val_if_fail (asn, NULL);
 
-	egg_asn1x_set_raw_element (egg_asn1x_node (asn, "reference", "certComplete", NULL),
-	                           g_memdup (cert->pValue, cert->ulValueLen),
+	ref = egg_asn1x_node (asn, "reference", NULL);
+	node = egg_asn1x_node (ref, "certComplete", NULL);
+
+	egg_asn1x_set_choice (ref, node);
+	egg_asn1x_set_raw_element (node, g_memdup (cert->pValue, cert->ulValueLen),
 	                           cert->ulValueLen, g_free);
 
 	trust = g_object_new (GKM_XDG_TYPE_TRUST, "module", module, "manager", manager, NULL);
 	trust->pv->asn = asn;
 
+	/* Encode it, which validates, and so we have read access to all the data */
+	trust->pv->data = egg_asn1x_encode (asn, NULL, &trust->pv->n_data);
+	if (!trust->pv->data) {
+		g_warning ("created invalid trust object: %s", egg_asn1x_message (asn));
+		return NULL;
+	}
+
 	return trust;
 }
 
@@ -592,24 +593,6 @@ gkm_xdg_trust_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE_
 	case CKA_MODIFIABLE:
 		return gkm_attribute_set_bool (attr, CK_FALSE);
 
-	/* Various trust flags */
-	case CKA_TRUST_SERVER_AUTH:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.server_auth);
-	case CKA_TRUST_CLIENT_AUTH:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.client_auth);
-	case CKA_TRUST_CODE_SIGNING:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.code_signing);
-	case CKA_TRUST_EMAIL_PROTECTION:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.email_protection);
-	case CKA_TRUST_IPSEC_END_SYSTEM:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.ipsec_end_system);
-	case CKA_TRUST_IPSEC_TUNNEL:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.ipsec_tunnel);
-	case CKA_TRUST_IPSEC_USER:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.ipsec_user);
-	case CKA_TRUST_TIME_STAMPING:
-		return gkm_attribute_set_ulong (attr, self->pv->netscape.time_stamping);
-
 	/* Certificate reference values */
 	case CKA_SUBJECT:
 		return trust_get_der (self, "subject", attr);
@@ -617,6 +600,8 @@ gkm_xdg_trust_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE_
 		return trust_get_integer (self, "serialNumber", attr);
 	case CKA_ISSUER:
 		return trust_get_der (self, "issuer", attr);
+	case CKA_G_CERTIFICATE_VALUE:
+		return trust_get_complete (self, attr);
 
 	/* Certificate hash values */
 	case CKA_CERT_MD5_HASH:
@@ -644,6 +629,32 @@ gkm_xdg_trust_expose_object (GkmObject *base, gboolean expose)
 		gkm_object_expose (value, expose);
 }
 
+static GkmTrustLevel
+gkm_xdg_trust_get_level (GkmTrust *base, const gchar *purpose)
+{
+	GkmXdgTrust *self = GKM_XDG_TRUST (base);
+	GkmAssertion *assertion;
+	GByteArray *key;
+	gulong type;
+
+	key = create_assertion_key (purpose, NULL);
+	assertion = g_hash_table_lookup (self->pv->assertions, key);
+	g_byte_array_unref (key);
+
+	if (!assertion)
+		return GKM_TRUST_UNKNOWN;
+
+	type = gkm_assertion_get_trust_type (assertion);
+	if (type == CKT_G_CERTIFICATE_TRUST_ANCHOR)
+		return GKM_TRUST_ANCHOR;
+	else if (type == CKT_G_CERTIFICATE_TRUST_EXCEPTION)
+		return GKM_TRUST_TRUSTED;
+	else if (type == CKT_G_CERTIFICATE_UNTRUSTED)
+		return GKM_TRUST_UNTRUSTED;
+	else
+		g_return_val_if_reached (GKM_TRUST_UNKNOWN);
+}
+
 static void
 gkm_xdg_trust_init (GkmXdgTrust *self)
 {
@@ -672,10 +683,12 @@ gkm_xdg_trust_class_init (GkmXdgTrustClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 	GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
+	GkmTrustClass *trust_class = GKM_TRUST_CLASS (klass);
 
 	gobject_class->finalize = gkm_xdg_trust_finalize;
 	gkm_class->get_attribute = gkm_xdg_trust_get_attribute;
 	gkm_class->expose_object = gkm_xdg_trust_expose_object;
+	trust_class->get_trust_level = gkm_xdg_trust_get_level;
 
 	QDATA_ASSERTION_KEY = g_quark_from_static_string ("gkm-xdg-trust-assertion-key");
 	g_type_class_add_private (klass, sizeof (GkmXdgTrustPrivate));
@@ -807,7 +820,7 @@ gkm_xdg_trust_create_for_assertion (GkmModule *module, GkmManager *manager,
 			return NULL;
 		}
 
-		trust = create_trust_for_certificate (module, manager, cert);
+		trust = create_trust_for_complete (module, manager, cert);
 
 	/* Not sure what this is */
 	} else {
@@ -827,42 +840,22 @@ gkm_xdg_trust_add_assertion (GkmXdgTrust *self, GkmAssertion *assertion,
 {
 	GkmAssertion *previous;
 	GByteArray *key;
-	GNode *asn;
-	gpointer data;
-	gsize n_data;
 
 	g_return_val_if_fail (GKM_XDG_IS_TRUST (self), NULL);
 	g_return_val_if_fail (GKM_IS_ASSERTION (assertion), NULL);
 	g_return_val_if_fail (!transaction || GKM_IS_TRANSACTION (transaction), NULL);
 
 	/* Build up a key if we don't have one */
-	key = lookup_assertion_key (assertion);
-	if (key == NULL) {
-		asn = egg_asn1x_create (xdg_asn1_tab, "TrustAssertion");
-		g_return_val_if_fail (asn, NULL);
+	key = lookup_or_create_assertion_key (assertion);
 
-		if (!save_assertion (asn, assertion))
-			g_return_val_if_reached (NULL);
+	/* Check if we alraedy have the assertion */
+	previous = g_hash_table_lookup (self->pv->assertions, key);
 
-		data = egg_asn1x_encode (asn, NULL, &n_data);
-		g_return_val_if_fail (data, NULL);
-
-		key = g_byte_array_new ();
-		g_byte_array_append (key, data, n_data);
-		stash_assertion_key (assertion, key);
-		g_byte_array_unref (key);
+	g_byte_array_unref (key);
 
-		g_free (data);
-		egg_asn1x_destroy (asn);
-
-	/* Already has a key, check if we alraedy have the assertion */
-	} else {
-		previous = g_hash_table_lookup (self->pv->assertions, key);
-
-		/* Just return previous assertion, don't add */
-		if (previous != NULL)
-			return previous;
-	}
+	/* Just return previous assertion, don't add */
+	if (previous != NULL)
+		return previous;
 
 	add_assertion_to_trust (self, assertion, transaction);
 	return assertion;
diff --git a/pkcs11/xdg-store/tests/test-xdg-trust.c b/pkcs11/xdg-store/tests/test-xdg-trust.c
index e50b695..5269705 100644
--- a/pkcs11/xdg-store/tests/test-xdg-trust.c
+++ b/pkcs11/xdg-store/tests/test-xdg-trust.c
@@ -32,6 +32,8 @@
 
 static GkmModule *module = NULL;
 static GkmSession *session = NULL;
+static gpointer cert_data = NULL;
+static gsize n_cert_data;
 
 /*
  * C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting, OU=Certification Services Division,
@@ -119,6 +121,9 @@ TESTING_SETUP (trust_setup)
 
 	rv = gkm_module_C_Login (module, gkm_session_get_handle (session), CKU_USER, NULL, 0);
 	g_assert (rv == CKR_OK);
+
+	cert_data = testing_data_read ("test-certificate-2.cer", &n_cert_data);
+	g_assert (cert_data);
 }
 
 TESTING_TEARDOWN (trust_teardown)
@@ -126,22 +131,18 @@ TESTING_TEARDOWN (trust_teardown)
 	test_xdg_module_leave_and_finalize ();
 	module = NULL;
 	session = NULL;
+
+	g_free (cert_data);
+	cert_data = NULL;
+	n_cert_data = 0;
 }
 
-TESTING_TEST (trust_load_object)
+TESTING_TEST (trust_load_objects)
 {
 	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
-/*	CK_TRUST trusted = CKT_NETSCAPE_TRUSTED;
-	CK_TRUST unknown = CKT_NETSCAPE_TRUST_UNKNOWN; */
 
-	/* This info matches what's in test-trust-1.der */
 	CK_ATTRIBUTE attrs[] = {
 		{ CKA_CLASS, &klass, sizeof (klass) },
-/*		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SERIAL_NUMBER, "\x00", 1 }, */
-/*		{ CKA_TRUST_CLIENT_AUTH, &trusted, sizeof (trusted) },
-		{ CKA_TRUST_CODE_SIGNING, &unknown, sizeof (unknown) },
-		{ CKA_TRUST_EMAIL_PROTECTION, &trusted, sizeof (trusted) }, */
 	};
 
 	CK_ULONG n_objects;
@@ -150,241 +151,484 @@ TESTING_TEST (trust_load_object)
 
 	rv = gkm_session_C_FindObjectsInit (session, attrs, G_N_ELEMENTS (attrs));
 	g_assert (rv == CKR_OK);
-
 	rv = gkm_session_C_FindObjects (session, objects, G_N_ELEMENTS (objects), &n_objects);
 	g_assert (rv == CKR_OK);
-
 	rv = gkm_session_C_FindObjectsFinal (session);
 	g_assert (rv == CKR_OK);
 
-	gkm_assert_cmpulong (n_objects, ==, 1);
+	gkm_assert_cmpulong (n_objects, >=, 1);
 }
 
-TESTING_TEST (trust_create_assertion)
+TESTING_TEST (trust_create_assertion_complete)
 {
 	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
 	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_ANCHOR;
 	CK_OBJECT_HANDLE object = 0;
-	gpointer data;
-	gsize n_data;
+	CK_OBJECT_HANDLE check = 0;
+	CK_ULONG n_objects = 0;
 	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
-		{ CKA_G_CERTIFICATE_VALUE, NULL, 0 },
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
 		{ CKA_CLASS, &klass, sizeof (klass) },
 		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
 		{ CKA_G_PURPOSE, "test-purpose", 12 },
 	};
 
-	data = testing_data_read ("test-certificate-2.cer", &n_data);
-	g_assert (data);
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
+
+	rv = gkm_session_C_FindObjectsInit (session, attrs, G_N_ELEMENTS (attrs));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, &check, 1, &n_objects);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	gkm_assert_cmpulong (n_objects, ==, 1);
+	gkm_assert_cmpulong (check, ==, object);
+}
 
-	attrs[0].pValue = data;
-	attrs[0].ulValueLen = n_data;
+TESTING_TEST (trust_complete_assertion_has_no_serial_or_issuer)
+{
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_ANCHOR;
+	CK_OBJECT_HANDLE object = 0;
+	CK_ATTRIBUTE check;
+	CK_RV rv;
+
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
+		{ CKA_CLASS, &klass, sizeof (klass) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
+	};
 
 	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
 	gkm_assert_cmprv (rv, ==, CKR_OK);
 	gkm_assert_cmpulong (object, !=, 0);
-}
 
+	check.type = CKA_SERIAL_NUMBER;
+	check.pValue = NULL;
+	check.ulValueLen = 0;
+	rv = gkm_session_C_GetAttributeValue (session, object, &check, 1);
+	gkm_assert_cmprv (rv, ==, CKR_ATTRIBUTE_TYPE_INVALID);
+
+	check.type = CKA_ISSUER;
+	check.pValue = NULL;
+	check.ulValueLen = 0;
+	rv = gkm_session_C_GetAttributeValue (session, object, &check, 1);
+	gkm_assert_cmprv (rv, ==, CKR_ATTRIBUTE_TYPE_INVALID);
+}
 
-#if 0
-TESTING_TEST (trust_create)
+TESTING_TEST (trust_complete_assertion_netscape_md5_hash)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_OBJECT_CLASS nklass = CKO_NETSCAPE_TRUST;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_EXCEPTION;
+	CK_OBJECT_HANDLE object = 0;
+	CK_OBJECT_HANDLE check = 0;
+	CK_ULONG n_objects = 0;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) }
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 	};
 
-	CK_OBJECT_HANDLE handle;
-	CK_RV rv;
+	CK_ATTRIBUTE lookup[] = {
+		{ CKA_CERT_MD5_HASH, (void*)MD5_CHECKSUM, XL (MD5_CHECKSUM) },
+		{ CKA_CLASS, &nklass, sizeof (nklass) },
+	};
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_OK);
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
 
-	rv = gkm_session_C_DestroyObject (session, handle);
-	g_assert (rv == CKR_OK);
-}
+	rv = gkm_session_C_FindObjectsInit (session, lookup, G_N_ELEMENTS (lookup));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, &check, 1, &n_objects);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
 
+	gkm_assert_cmpulong (check, !=, 0);
+	gkm_assert_cmpulong (n_objects, >, 0);
+}
 
-TESTING_TEST (trust_create_invalid_attrs)
+TESTING_TEST (trust_complete_assertion_netscape_sha1_hash)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_OBJECT_CLASS nklass = CKO_NETSCAPE_TRUST;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_EXCEPTION;
+	CK_OBJECT_HANDLE object = 0;
+	CK_OBJECT_HANDLE check = 0;
+	CK_ULONG n_objects = 0;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
 		{ CKA_CLASS, &klass, sizeof (klass) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 	};
 
-	CK_OBJECT_HANDLE handle;
-	CK_RV rv;
+	CK_ATTRIBUTE lookup[] = {
+		{ CKA_CERT_SHA1_HASH, (void*)SHA1_CHECKSUM, XL (SHA1_CHECKSUM) },
+		{ CKA_CLASS, &nklass, sizeof (nklass) },
+	};
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_TEMPLATE_INCOMPLETE);
+	rv = gkm_session_C_FindObjectsInit (session, lookup, G_N_ELEMENTS (lookup));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, &check, 1, &n_objects);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	gkm_assert_cmpulong (check, !=, 0);
+	gkm_assert_cmpulong (n_objects, >, 0);
 }
 
-TESTING_TEST (trust_create_invalid_der)
+TESTING_TEST (trust_create_assertion_missing_type)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_OBJECT_HANDLE object = 0;
+	CK_RV rv;
 
+	/* Missing CKT_G_CERTIFICATE_TRUST_ANCHOR */
 	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, "test", 4 },
-		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) }
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 	};
 
-	CK_OBJECT_HANDLE handle;
-	CK_RV rv;
-
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_TEMPLATE_INCOMPLETE);
 }
 
-TESTING_TEST (trust_create_invalid_serial)
+TESTING_TEST (trust_create_assertion_bad_type)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = 0xFFFF;
+	CK_OBJECT_HANDLE object = 0;
+	CK_RV rv;
 
+	/* Missing CKA_G_CERTIFICATE_VALUE */
 	CK_ATTRIBUTE attrs[] = {
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SERIAL_NUMBER, "", 0 }
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 	};
 
-	CK_OBJECT_HANDLE handle;
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_TEMPLATE_INCONSISTENT);
+}
+
+TESTING_TEST (trust_create_assertion_missing_cert_value)
+{
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_ANCHOR;
+	CK_OBJECT_HANDLE object = 0;
 	CK_RV rv;
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+	/* Missing CKA_G_CERTIFICATE_VALUE */
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_CLASS, &klass, sizeof (klass) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
+	};
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_TEMPLATE_INCOMPLETE);
 }
 
-TESTING_TEST (trust_create_with_sha1)
+TESTING_TEST (trust_create_assertion_bad_cert_value)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_ANCHOR;
+	CK_OBJECT_HANDLE object = 0;
+	CK_RV rv;
 
+	/* Bad CKA_G_CERTIFICATE_VALUE */
 	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, "12", 2 },
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) },
-		{ CKA_CERT_SHA1_HASH, (void*)SHA1_CHECKSUM, XL (SHA1_CHECKSUM) }
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 	};
 
-	CK_OBJECT_HANDLE handle;
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+TESTING_TEST (trust_create_assertion_null_cert_value)
+{
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_ANCHOR;
+	CK_OBJECT_HANDLE object = 0;
 	CK_RV rv;
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_OK);
+	/* Bad CKA_G_CERTIFICATE_VALUE */
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, NULL, 0 },
+		{ CKA_CLASS, &klass, sizeof (klass) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
+	};
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_ATTRIBUTE_VALUE_INVALID);
 }
 
-TESTING_TEST (trust_create_with_md5)
+TESTING_TEST (trust_create_assertion_for_untrusted)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_UNTRUSTED;
+	CK_OBJECT_HANDLE object = 0;
+	CK_OBJECT_HANDLE check = 0;
+	CK_ULONG n_objects = 0;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) },
-		{ CKA_CERT_MD5_HASH, (void*)MD5_CHECKSUM, XL (MD5_CHECKSUM) }
+		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) }
 	};
 
-	CK_OBJECT_HANDLE handle;
-	CK_RV rv;
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_OK);
+	rv = gkm_session_C_FindObjectsInit (session, attrs, G_N_ELEMENTS (attrs));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, &check, 1, &n_objects);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	gkm_assert_cmpulong (n_objects, ==, 1);
+	gkm_assert_cmpulong (check, ==, object);
 }
 
-TESTING_TEST (trust_create_with_subject)
+TESTING_TEST (trust_create_assertion_for_untrusted_no_purpose)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_UNTRUSTED;
+	CK_OBJECT_HANDLE object = 0;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SUBJECT, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) }
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) },
+		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) }
 	};
 
-	CK_OBJECT_HANDLE handle;
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_TEMPLATE_INCOMPLETE);
+}
+
+TESTING_TEST (trust_create_assertion_for_untrusted_no_serial)
+{
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_UNTRUSTED;
+	CK_OBJECT_HANDLE object = 0;
 	CK_RV rv;
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_OK);
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_CLASS, &klass, sizeof (klass) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
+		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) }
+	};
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_TEMPLATE_INCOMPLETE);
 }
 
-TESTING_TEST (trust_create_invalid_checksum)
+TESTING_TEST (trust_create_assertion_twice)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_UNTRUSTED;
+	CK_OBJECT_HANDLE object_1 = 0;
+	CK_OBJECT_HANDLE object_2 = 0;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) },
-		{ CKA_CERT_SHA1_HASH, "test", 4 }
+		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) }
 	};
 
-	CK_OBJECT_HANDLE handle;
-	CK_RV rv;
+	/* Should end up pointing to the same object */
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object_1);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object_1, !=, 0);
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object_2);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object_2, !=, 0);
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_ATTRIBUTE_VALUE_INVALID);
+	gkm_assert_cmpulong (object_1, ==, object_2);
 }
 
-TESTING_TEST (trust_create_with_trusted)
+TESTING_TEST (trust_untrusted_assertion_has_no_cert_value)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
-	CK_TRUST trust = CKT_NETSCAPE_TRUSTED;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_UNTRUSTED;
+	CK_OBJECT_HANDLE object = 0;
+	CK_ATTRIBUTE check;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "test-purpose", 12 },
 		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) },
-		{ CKA_TRUST_EMAIL_PROTECTION, &trust, sizeof (trust) }
+		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) }
 	};
 
-	CK_OBJECT_HANDLE handle;
-	CK_RV rv;
+	/* Created as untrusted, should have no CKA_G_CERTIFICATE_VALUE */
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_OK);
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
+
+	check.type = CKA_G_CERTIFICATE_VALUE;
+	check.pValue = NULL;
+	check.ulValueLen = 0;
+	rv = gkm_session_C_GetAttributeValue (session, object, &check, 1);
+	gkm_assert_cmprv (rv, ==, CKR_ATTRIBUTE_TYPE_INVALID);
 }
 
-TESTING_TEST (trust_create_with_trusted_and_save)
+TESTING_TEST (trust_create_assertion_complete_on_token)
 {
-	CK_OBJECT_CLASS klass = CKO_NETSCAPE_TRUST;
-	CK_TRUST trusted = CKT_NETSCAPE_TRUSTED;
-	CK_TRUST untrusted = CKT_NETSCAPE_UNTRUSTED;
-	CK_TRUST unknown = CKT_NETSCAPE_TRUST_UNKNOWN;
-	CK_BBOOL true = CK_TRUE;
+	CK_OBJECT_CLASS klass = CKO_G_TRUST_ASSERTION;
+	CK_ASSERTION_TYPE atype = CKT_G_CERTIFICATE_TRUST_EXCEPTION;
+	CK_OBJECT_HANDLE object = 0;
+	CK_OBJECT_HANDLE check = 0;
+	CK_OBJECT_HANDLE results[8];
+	CK_BBOOL token = CK_TRUE;
+	CK_ULONG n_objects = 0;
+	CK_RV rv;
 
 	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
 		{ CKA_CLASS, &klass, sizeof (klass) },
-		{ CKA_ISSUER, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SUBJECT, (void*)DER_ISSUER, XL (DER_ISSUER) },
-		{ CKA_SERIAL_NUMBER, (void*)SERIAL_NUMBER, XL (SERIAL_NUMBER) },
-		{ CKA_TOKEN, &true, sizeof (true) },
-		{ 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_TRUST_SERVER_AUTH, &untrusted, sizeof (untrusted) },
-		{ CKA_TRUST_CLIENT_AUTH, &trusted, sizeof (trusted) },
-		{ CKA_TRUST_CODE_SIGNING, &unknown, sizeof (unknown) },
-		{ CKA_TRUST_EMAIL_PROTECTION, &trusted, sizeof (trusted) },
-		{ CKA_TRUST_TIME_STAMPING, &untrusted, sizeof (untrusted) },
-		{ CKA_TRUST_IPSEC_END_SYSTEM, &untrusted, sizeof (untrusted) },
-		{ CKA_TRUST_IPSEC_TUNNEL, &untrusted, sizeof (untrusted) },
-		{ CKA_TRUST_IPSEC_USER, &untrusted, sizeof (untrusted) },
+		{ CKA_G_ASSERTION_TYPE, &atype, sizeof (atype) },
+		{ CKA_G_PURPOSE, "other", 5 },
+		{ CKA_TOKEN, &token, sizeof (token) },
 	};
 
-	CK_OBJECT_HANDLE handle;
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &check);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (check, !=, 0);
+
+	gkm_assert_cmpulong (check, ==, object);
+
+	rv = gkm_session_C_FindObjectsInit (session, attrs, G_N_ELEMENTS (attrs));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, results, G_N_ELEMENTS (results), &n_objects);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	gkm_assert_cmpulong (n_objects, ==, 1);
+	gkm_assert_cmpulong (results[0], ==, object);
+}
+
+static void
+_assert_positive_netscape (CK_ASSERTION_TYPE assertion_type, const gchar *purpose,
+                           CK_ATTRIBUTE_TYPE netscape_type, CK_TRUST netscape_trust,
+                           const gchar *description)
+{
+	CK_OBJECT_CLASS aklass = CKO_G_TRUST_ASSERTION;
+	CK_OBJECT_CLASS nklass = CKO_NETSCAPE_TRUST;
+	CK_OBJECT_HANDLE object = 0;
+	CK_OBJECT_HANDLE results[256];
+	CK_ULONG n_results = 0;
+	CK_BYTE checksum[20];
+	gsize n_checksum;
+	CK_ATTRIBUTE attr;
+	CK_TRUST check;
+	GChecksum *md;
+	CK_BBOOL fval = CK_FALSE;
 	CK_RV rv;
 
-	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &handle);
-	g_assert (rv == CKR_OK);
+	CK_ATTRIBUTE attrs[] = {
+		{ CKA_G_CERTIFICATE_VALUE, cert_data, n_cert_data },
+		{ CKA_CLASS, &aklass, sizeof (aklass) },
+		{ CKA_G_ASSERTION_TYPE, &assertion_type, sizeof (assertion_type) },
+		{ CKA_G_PURPOSE, (void*)purpose, strlen (purpose) },
+		{ CKA_TOKEN, &fval, sizeof (fval) },
+	};
+
+	CK_ATTRIBUTE lookup[] = {
+		{ CKA_CLASS, &nklass, sizeof (nklass) },
+		{ CKA_TOKEN, &fval, sizeof (fval) },
+		{ CKA_CERT_SHA1_HASH, checksum, sizeof (checksum) },
+	};
+
+	rv = gkm_session_C_CreateObject (session, attrs, G_N_ELEMENTS (attrs), &object);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	gkm_assert_cmpulong (object, !=, 0);
+
+	md = g_checksum_new (G_CHECKSUM_SHA1);
+	g_checksum_update (md, cert_data, n_cert_data);
+	n_checksum = sizeof (checksum);
+	g_checksum_get_digest (md, checksum, &n_checksum);
+	g_assert (n_checksum == sizeof (checksum));
+
+	rv = gkm_session_C_FindObjectsInit (session, lookup, G_N_ELEMENTS (lookup));
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjects (session, results, G_N_ELEMENTS (results), &n_results);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+	rv = gkm_session_C_FindObjectsFinal (session);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	gkm_assert_cmpulong (n_results, ==, 1);
+
+	check = (CK_ULONG)-1;
+	attr.type = netscape_type;
+	attr.pValue = &check;
+	attr.ulValueLen = sizeof (check);
+
+	rv = gkm_session_C_GetAttributeValue (session, results[0], &attr, 1);
+	gkm_assert_cmprv (rv, ==, CKR_OK);
+
+	if (check != netscape_trust)
+		g_warning ("netscape trust was not mapped correctly: \"%s\"", description);
+	gkm_assert_cmpulong (check, ==, netscape_trust);
+}
+
+/* Some macros for intelligent failure messages */
+#define assert_positive_netscape(a, b, c, d) \
+	_assert_positive_netscape (a, b, c, d, #a ", " #b ", " #c ", " #d)
+
+TESTING_TEST (trust_netscape_map_email)
+{
+	assert_positive_netscape (CKT_G_CERTIFICATE_TRUST_EXCEPTION, "1.3.6.1.5.5.7.3.4",
+	                          CKA_TRUST_EMAIL_PROTECTION, CKT_NETSCAPE_TRUSTED);
+}
+
+TESTING_TEST (trust_netscape_map_email_anchor)
+{
+	assert_positive_netscape (CKT_G_CERTIFICATE_TRUST_ANCHOR, "1.3.6.1.5.5.7.3.4",
+	                          CKA_TRUST_EMAIL_PROTECTION, CKT_NETSCAPE_TRUSTED_DELEGATOR);
 }
-#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]