gnome-keyring r1005 - in trunk: . pk pk/tests pk/tests/test-data pkcs11



Author: nnielsen
Date: Mon Jan 14 01:22:17 2008
New Revision: 1005
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1005&view=rev

Log:
	* pk/gkr-pk-cert.c:
	* pk/gkr-pk-cert.h:
	* pk/gkr-pk-netscape-trust.c:
	* pk/gkr-pk-object-manager.c:
	* pk/gkr-pk-object-storage.c:
	* pk/gkr-pk-object-storage.h:
	* pk/gkr-pk-object.c:
	* pk/gkr-pk-object.h:
	* pk/gkr-pk-privkey.c:
	* pk/gkr-pk-privkey.h:
	* pk/gkr-pk-pubkey.c:
	* pk/gkr-pk-pubkey.h:
	* pk/gkr-pk-util.c:
	* pk/gkr-pk-util.h:
	* pk/tests/Makefile.am:
	* pk/tests/check-attribute.c:
	* pk/tests/unit-test-pk-cert.c:
	* pk/tests/unit-test-pk-key.c: (added)
	* pk/tests/unit-test-pk-netscape-trust.c:
	* pk/tests/test-data/privkey-1.key: (renamed from .crt)
	* pk/tests/test-data/privkey-3.key: (added)
	* pkcs11/gkr-pkcs11-daemon-session.c:
	* pkcs11/gkr-pkcs11-dsa.c: Proper support for creating and destroying
	objects through PKCS#11 (no token save functionality yet). Also proper
	infrastructure for setting of attributes.

Added:
   trunk/pk/tests/test-data/privkey-1.key
      - copied unchanged from r1003, /trunk/pk/tests/test-data/privkey-1.crt
   trunk/pk/tests/test-data/privkey-3.key   (contents, props changed)
   trunk/pk/tests/unit-test-pk-key.c
Removed:
   trunk/pk/tests/test-data/privkey-1.crt
Modified:
   trunk/ChangeLog
   trunk/pk/gkr-pk-cert.c
   trunk/pk/gkr-pk-cert.h
   trunk/pk/gkr-pk-netscape-trust.c
   trunk/pk/gkr-pk-object-manager.c
   trunk/pk/gkr-pk-object-storage.c
   trunk/pk/gkr-pk-object-storage.h
   trunk/pk/gkr-pk-object.c
   trunk/pk/gkr-pk-object.h
   trunk/pk/gkr-pk-privkey.c
   trunk/pk/gkr-pk-privkey.h
   trunk/pk/gkr-pk-pubkey.c
   trunk/pk/gkr-pk-pubkey.h
   trunk/pk/gkr-pk-util.c
   trunk/pk/gkr-pk-util.h
   trunk/pk/tests/Makefile.am
   trunk/pk/tests/check-attribute.c
   trunk/pk/tests/unit-test-pk-cert.c
   trunk/pk/tests/unit-test-pk-netscape-trust.c
   trunk/pkcs11/gkr-pkcs11-calls.h
   trunk/pkcs11/gkr-pkcs11-daemon-session.c
   trunk/pkcs11/gkr-pkcs11-dsa.c
   trunk/pkcs11/gkr-pkcs11-module.c

Modified: trunk/pk/gkr-pk-cert.c
==============================================================================
--- trunk/pk/gkr-pk-cert.c	(original)
+++ trunk/pk/gkr-pk-cert.c	Mon Jan 14 01:22:17 2008
@@ -295,6 +295,14 @@
 }
 
 static CK_RV
+read_certificate_purpose (GkrPkCert *cert, GQuark oid, CK_ATTRIBUTE_PTR attr)
+{
+	gboolean value = check_certificate_purpose (cert, oid);
+	gkr_pk_attribute_set_boolean (attr, value);
+	return CKR_OK;
+}
+
+static CK_RV
 read_certificate_purposes (GkrPkCert *cert, CK_ATTRIBUTE_PTR attr)
 {
 	GQuark *quarks, *q;
@@ -392,162 +400,104 @@
 		break;
 	}
 }
-            
-static CK_RV 
-gkr_pk_cert_get_bool_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
+
+static CK_RV
+gkr_pk_cert_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
 {
 	GkrPkCert *cert = GKR_PK_CERT (obj);
-	gboolean val;
+	const guchar *cdata = NULL;
+	gkrconstunique keyid;
+	CK_ULONG value;
+	gchar *index;
+	guchar *data;
+	gsize n_data;
+	time_t time;
+	CK_RV ret;
+	
+	g_assert (!attr->pValue);
 	
 	switch (attr->type)
 	{
-	case CKA_TOKEN:
-		val = TRUE;
-		break;
-	
-	case CKA_PRIVATE:
-	case CKA_MODIFIABLE:
-		val = FALSE;
-		break;
-		
 	case CKA_GNOME_PURPOSE_RESTRICTED:
-		val = has_certificate_purposes (cert);
-		break;
+		gkr_pk_attribute_set_boolean (attr, has_certificate_purposes (cert));
+		return CKR_OK;
 		
 	case CKA_GNOME_PURPOSE_SSH_AUTH:
-		val = check_certificate_purpose (cert, OID_USAGE_SSH_AUTH);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_SSH_AUTH, attr);
 		
 	case CKA_GNOME_PURPOSE_SERVER_AUTH:
-		val = check_certificate_purpose (cert, OID_USAGE_SERVER_AUTH);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_SERVER_AUTH, attr);
 		
 	case CKA_GNOME_PURPOSE_CLIENT_AUTH:
-		val = check_certificate_purpose (cert, OID_USAGE_CLIENT_AUTH);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_CLIENT_AUTH, attr);
 		
 	case CKA_GNOME_PURPOSE_CODE_SIGNING:
-		val = check_certificate_purpose (cert, OID_USAGE_CODE_SIGNING);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_CODE_SIGNING, attr);
 		
 	case CKA_GNOME_PURPOSE_EMAIL_PROTECTION:
-		val = check_certificate_purpose (cert, OID_USAGE_EMAIL);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_EMAIL, attr);
 		
 	case CKA_GNOME_PURPOSE_IPSEC_END_SYSTEM:
-		val = check_certificate_purpose (cert, OID_USAGE_IPSEC_ENDPOINT);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_IPSEC_ENDPOINT, attr);
 		
 	case CKA_GNOME_PURPOSE_IPSEC_TUNNEL:
-		val = check_certificate_purpose (cert, OID_USAGE_IPSEC_TUNNEL);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_IPSEC_TUNNEL, attr);
 		
 	case CKA_GNOME_PURPOSE_IPSEC_USER:
-		val = check_certificate_purpose (cert, OID_USAGE_IPSEC_USER);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_IPSEC_USER, attr);
 		
 	case CKA_GNOME_PURPOSE_TIME_STAMPING:
-		val = check_certificate_purpose (cert, OID_USAGE_TIME_STAMPING);
-		break;
+		return read_certificate_purpose (cert, OID_USAGE_TIME_STAMPING, attr);
 		
 	/* TODO: Until we can figure out a trust system */
 	case CKA_TRUSTED:
-		val = FALSE;
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 		
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_boolean (attr, val);
-	return CKR_OK;
-}
-
-static CK_RV 
-gkr_pk_cert_get_ulong_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkCert *cert = GKR_PK_CERT (obj);
-	gulong val;
-	gchar *value;
-	guchar *extension;
-	gsize n_extension;
-	gboolean is_ca;
-	CK_RV ret;
-	int res;
-	
-	switch (attr->type)
-	{
 	case CKA_CLASS:
-		val = CKO_CERTIFICATE;
-		break;
+		gkr_pk_attribute_set_ulong (attr, CKO_CERTIFICATE);
+		return CKR_OK;
 		
 	case CKA_CERTIFICATE_TYPE:
-		val = CKC_X_509;
-		break;
+		gkr_pk_attribute_set_ulong (attr, CKC_X_509);
+		return CKR_OK;
 		
 	case CKA_CERTIFICATE_CATEGORY:
 		if ((ret = load_certificate (cert)) != CKR_OK)
 			return ret;
-		val = 0; /* unknown */
-		extension = gkr_pk_cert_get_extension (cert, OID_BASIC_CONSTRAINTS, &n_extension, NULL);
-		if (extension) {
-			res = gkr_pkix_der_read_basic_constraints (extension, n_extension, &is_ca, NULL);
-			g_free (extension);
+		value = 0; /* unknown */
+		data = gkr_pk_cert_get_extension (cert, OID_BASIC_CONSTRAINTS, &n_data, NULL);
+		if (data) {
+			GkrParseResult res;
+			gboolean is_ca;
+
+			res = gkr_pkix_der_read_basic_constraints (data, n_data, &is_ca, NULL);
+			g_free (data);
 			if (res != GKR_PARSE_SUCCESS)
 				return CKR_GENERAL_ERROR;
 			if (is_ca)
-				val = 2; /* authority */
+				value = 2; /* authority */
 		}
-		break;
+		gkr_pk_attribute_set_ulong (attr, value);
+		return CKR_OK;
 	
 	case CKA_GNOME_USER_TRUST:
-		val = CKT_GNOME_UNKNOWN;
+		value = CKT_GNOME_UNKNOWN;
 		
 		/* Explicity set? */
-		value = gkr_pk_index_get_string (obj, "user-trust");
-		if (value) {
-			if (g_str_equal (value, "trusted"))
-				val = CKT_GNOME_TRUSTED;
-			else if (g_str_equal (value, "untrusted"))
-				val = CKT_GNOME_UNTRUSTED;
-			g_free (value);
+		index = gkr_pk_index_get_string (obj, "user-trust");
+		if (index) {
+			if (g_str_equal (index, "trusted"))
+				value = CKT_GNOME_TRUSTED;
+			else if (g_str_equal (index, "untrusted"))
+				value = CKT_GNOME_UNTRUSTED;
+			g_free (index);
 
 		/* With a private key it's trusted by default */				
 		} else if (has_private_key (cert)) {
-			val = CKT_GNOME_TRUSTED;
-				
+			value = CKT_GNOME_TRUSTED;	
 		} 
-		break;		
-	
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_ulong (attr, val);
-	return CKR_OK;
-}
-
-static CK_RV
-gkr_pk_cert_get_data_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkCert *cert = GKR_PK_CERT (obj);
-	const guchar *cdata = NULL;
-	gkrconstunique keyid;
-	gchar *label;
-	guchar *data;
-	gsize n_data;
-	CK_RV ret;
-	
-	g_assert (!attr->pValue);
-	
-	switch (attr->type)
-	{
-	case CKA_LABEL:
-		g_object_get (obj, "label", &label, NULL);
-		if (!label)
-			label = gkr_location_to_display (obj->location);
-		gkr_pk_attribute_set_string (attr, label);
-		g_free (label);
+		gkr_pk_attribute_set_ulong (attr, value);
 		return CKR_OK;
 		
 	case CKA_ID:
@@ -606,6 +556,19 @@
 		gkr_pk_attribute_set_data (attr, data, 3);
 		g_free (data);
 		return CKR_OK;
+		
+	case CKA_START_DATE:
+	case CKA_END_DATE:
+		if ((ret = load_certificate (cert)) != CKR_OK)
+			return ret;
+		if (!gkr_pkix_asn1_read_time (cert->data->asn1, 
+		                              attr->type == CKA_START_DATE ? 
+		                                       "tbsCertificate.validity.notBefore" : 
+		                                       "tbsCertificate.validity.notAfter",
+		                              &time))
+			g_return_val_if_reached (CKR_GENERAL_ERROR);
+		gkr_pk_attribute_set_date (attr, time);
+		return CKR_OK;
 	
 	/* These are only used for strange online certificates which we don't support */	
 	case CKA_URL:
@@ -620,38 +583,7 @@
 		break;
 	};
 
-	return CKR_ATTRIBUTE_TYPE_INVALID;
-}
-
-static CK_RV 
-gkr_pk_cert_get_date_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkCert *cert = GKR_PK_CERT (obj);
-	time_t time;
-	CK_RV ret;
-	
-	switch (attr->type) 
-	{
-	case CKA_START_DATE:
-		if ((ret = load_certificate (cert)) != CKR_OK)
-			return ret;
-		if (!gkr_pkix_asn1_read_time (cert->data->asn1, "tbsCertificate.validity.notBefore", &time))
-			g_return_val_if_reached (CKR_GENERAL_ERROR);
-		break;
-	
-	case CKA_END_DATE:
-		if ((ret = load_certificate (cert)) != CKR_OK)
-			return ret;
-		if (!gkr_pkix_asn1_read_time (cert->data->asn1, "tbsCertificate.validity.notAfter", &time))
-			g_return_val_if_reached (CKR_GENERAL_ERROR);
-		break;
-	
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_date (attr, time);
-	return CKR_OK;
+	return GKR_PK_OBJECT_CLASS (gkr_pk_cert_parent_class)->get_attribute (obj, attr);
 }
 
 static void
@@ -683,10 +615,7 @@
 	gkr_pk_cert_parent_class = g_type_class_peek_parent (klass);
 	
 	parent_class = GKR_PK_OBJECT_CLASS (klass);
-	parent_class->get_bool_attribute = gkr_pk_cert_get_bool_attribute;
-	parent_class->get_ulong_attribute = gkr_pk_cert_get_ulong_attribute;
-	parent_class->get_data_attribute = gkr_pk_cert_get_data_attribute;
-	parent_class->get_date_attribute = gkr_pk_cert_get_date_attribute;
+	parent_class->get_attribute = gkr_pk_cert_get_attribute;
 	
 	gobject_class->get_property = gkr_pk_cert_get_property;
 	gobject_class->set_property = gkr_pk_cert_set_property;
@@ -722,6 +651,43 @@
 	return cert;
 }
 
+CK_RV
+gkr_pk_cert_create (GkrPkObjectManager* manager, GArray* array, 
+                    GkrPkObject **object)
+{
+	ASN1_TYPE asn;
+	CK_ATTRIBUTE_PTR attr;
+ 	CK_KEY_TYPE type;
+ 	
+	g_return_val_if_fail (GKR_IS_PK_OBJECT_MANAGER (manager), CKR_GENERAL_ERROR);
+	g_return_val_if_fail (array, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (object, CKR_GENERAL_ERROR);
+	
+	*object = NULL;
+	
+	if (!gkr_pk_attributes_ulong (array, CKA_CERTIFICATE_TYPE, &type))
+ 		return CKR_TEMPLATE_INCOMPLETE;
+
+	if (type != CKC_X_509)
+		return CKR_ATTRIBUTE_VALUE_INVALID;
+
+	attr = gkr_pk_attributes_find (array, CKA_VALUE);
+	if (!attr)
+		return CKR_TEMPLATE_INCOMPLETE;
+		
+	g_return_val_if_fail (attr->pValue, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (attr->ulValueLen, CKR_GENERAL_ERROR);
+	
+	if (gkr_pkix_der_read_certificate (attr->pValue, attr->ulValueLen, &asn) != GKR_PARSE_SUCCESS)
+		return CKR_ATTRIBUTE_VALUE_INVALID;
+	
+	/* All the attributes that we used up */	
+	gkr_pk_attributes_consume (array, CKA_CERTIFICATE_TYPE, CKA_VALUE, -1);
+	
+	*object = GKR_PK_OBJECT (gkr_pk_cert_new (manager, 0, asn));
+	return CKR_OK;
+}
+
 gboolean
 gkr_pk_cert_has_extension (GkrPkCert *cert, GQuark oid, gboolean *critical)
 {

Modified: trunk/pk/gkr-pk-cert.h
==============================================================================
--- trunk/pk/gkr-pk-cert.h	(original)
+++ trunk/pk/gkr-pk-cert.h	Mon Jan 14 01:22:17 2008
@@ -55,6 +55,9 @@
 GkrPkCert*          gkr_pk_cert_new                (GkrPkObjectManager *manager, 
                                                     GQuark location, ASN1_TYPE asn1);
 
+CK_RV               gkr_pk_cert_create             (GkrPkObjectManager* manager, 
+                                                    GArray* array, GkrPkObject **object);
+                                                    
 gboolean            gkr_pk_cert_has_extension      (GkrPkCert *cert, GQuark oid, 
                                                     gboolean *critical);
 

Modified: trunk/pk/gkr-pk-netscape-trust.c
==============================================================================
--- trunk/pk/gkr-pk-netscape-trust.c	(original)
+++ trunk/pk/gkr-pk-netscape-trust.c	Mon Jan 14 01:22:17 2008
@@ -82,7 +82,7 @@
 }
 
 static CK_RV
-has_key_usage (GkrPkNetscapeTrust *trust, guint check, gulong *val)
+has_key_usage (GkrPkNetscapeTrust *trust, guint check, CK_ULONG *val)
 {
 	GkrParseResult res;
 	guchar *extension;
@@ -115,7 +115,17 @@
 }
 
 static CK_RV
-has_enhanced_usage (GkrPkNetscapeTrust *trust, CK_ATTRIBUTE_TYPE type, gulong *val)
+read_key_usage (GkrPkNetscapeTrust *trust, guint check, CK_ATTRIBUTE_PTR attr)
+{
+	CK_ULONG value;
+	CK_RV ret = has_key_usage (trust, check, &value);
+	if (ret == CKR_OK)
+		gkr_pk_attribute_set_ulong (attr, value);
+	return ret;
+}
+
+static CK_RV
+has_enhanced_usage (GkrPkNetscapeTrust *trust, CK_ATTRIBUTE_TYPE type, CK_ULONG *val)
 {
 	CK_RV ret;
 	CK_BBOOL bval;
@@ -167,6 +177,17 @@
 }
 
 static CK_RV
+read_enhanced_usage (GkrPkNetscapeTrust *trust, CK_ATTRIBUTE_TYPE type, 
+                     CK_ATTRIBUTE_PTR attr)
+{
+	CK_ULONG value;
+	CK_RV ret = has_enhanced_usage (trust, type, &value);
+	if (ret == CKR_OK)
+		gkr_pk_attribute_set_ulong (attr, value);
+	return ret;
+}
+
+static CK_RV
 hash_certificate (GkrPkNetscapeTrust *trust, int algo, CK_ATTRIBUTE_PTR result)
 {
 	const guchar *raw;
@@ -229,113 +250,72 @@
 		break;
 	}
 }
-            
-static CK_RV 
-gkr_pk_netscape_trust_get_bool_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
+
+static CK_RV
+gkr_pk_netscape_trust_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
 {
-	gboolean val;
+	GkrPkNetscapeTrust *trust = GKR_PK_NETSCAPE_TRUST (obj);
 	
+	g_assert (!attr->pValue);
 	switch (attr->type)
 	{
-	case CKA_TOKEN:
-	case CKA_MODIFIABLE:
-		val = TRUE;
-		break;
-		
 	case CKA_PRIVATE:
 	case CKA_TRUST_STEP_UP_APPROVED:
-		val = FALSE;
-		break;
-	
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_boolean (attr, val);
-	return CKR_OK;
-}
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 
-static CK_RV 
-gkr_pk_netscape_trust_get_ulong_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkNetscapeTrust *trust = GKR_PK_NETSCAPE_TRUST (obj);
-	CK_RV ret = CKR_OK;
-	gulong val;
-	
-	switch (attr->type)
-	{
 	case CKA_CLASS:
-		val = CKO_NETSCAPE_TRUST;
-		break;
+		gkr_pk_attribute_set_ulong (attr, CKO_NETSCAPE_TRUST);
+		return CKR_OK;
 		
 	/* Key restrictions */
 	case CKA_TRUST_DIGITAL_SIGNATURE:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_DIGITAL_SIGNATURE, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_DIGITAL_SIGNATURE, attr);
+
 	case CKA_TRUST_NON_REPUDIATION:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_NON_REPUDIATION, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_NON_REPUDIATION, attr);
+
 	case CKA_TRUST_KEY_ENCIPHERMENT:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_KEY_ENCIPHERMENT, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_KEY_ENCIPHERMENT, attr);
+
 	case CKA_TRUST_DATA_ENCIPHERMENT:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_DATA_ENCIPHERMENT, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_DATA_ENCIPHERMENT, attr);
+
 	case CKA_TRUST_KEY_AGREEMENT:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_KEY_AGREEMENT, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_KEY_AGREEMENT, attr);
+
 	case CKA_TRUST_KEY_CERT_SIGN:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_KEY_CERT_SIGN, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_KEY_CERT_SIGN, attr);
+
 	case CKA_TRUST_CRL_SIGN:
-		ret = has_key_usage (trust, PKIX_KEY_USAGE_CRL_SIGN, &val);
-		break;
+		return read_key_usage (trust, PKIX_KEY_USAGE_CRL_SIGN, attr);
 
 	/* Various trust flags */
 	case CKA_TRUST_SERVER_AUTH:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_SERVER_AUTH, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_SERVER_AUTH, attr);
+
 	case CKA_TRUST_CLIENT_AUTH:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_CLIENT_AUTH, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_CLIENT_AUTH, attr);
+
 	case CKA_TRUST_CODE_SIGNING:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_CODE_SIGNING, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_CODE_SIGNING, attr);
+
 	case CKA_TRUST_EMAIL_PROTECTION:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_EMAIL_PROTECTION, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_EMAIL_PROTECTION, attr);
+
 	case CKA_TRUST_IPSEC_END_SYSTEM:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_IPSEC_END_SYSTEM, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_IPSEC_END_SYSTEM, attr);
+
 	case CKA_TRUST_IPSEC_TUNNEL:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_IPSEC_TUNNEL, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_IPSEC_TUNNEL, attr);
+
 	case CKA_TRUST_IPSEC_USER:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_IPSEC_USER, &val);
-		break;
-	case CKA_TRUST_TIME_STAMPING:
-		ret = has_enhanced_usage (trust, CKA_GNOME_PURPOSE_TIME_STAMPING, &val);
-		break;
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_IPSEC_USER, attr);
 
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	if (ret == CKR_OK)
-		gkr_pk_attribute_set_ulong (attr, val);
-	return ret;
-}
+	case CKA_TRUST_TIME_STAMPING:
+		return read_enhanced_usage (trust, CKA_GNOME_PURPOSE_TIME_STAMPING, attr);
 
-static CK_RV
-gkr_pk_netscape_trust_get_data_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkNetscapeTrust *trust = GKR_PK_NETSCAPE_TRUST (obj);
-	
-	g_assert (!attr->pValue);
-	switch (attr->type)
-	{
 	case CKA_ID:
-	case CKA_LABEL:
 	case CKA_SUBJECT:
 	case CKA_SERIAL_NUMBER:
 	case CKA_ISSUER:
@@ -350,7 +330,7 @@
 		break;
 	};
 
-	return CKR_ATTRIBUTE_TYPE_INVALID;
+	return GKR_PK_OBJECT_CLASS (gkr_pk_netscape_trust_parent_class)->get_attribute (obj, attr);
 }
 
 static void
@@ -379,9 +359,7 @@
 	gkr_pk_netscape_trust_parent_class = g_type_class_peek_parent (klass);
 	
 	parent_class = GKR_PK_OBJECT_CLASS (klass);
-	parent_class->get_bool_attribute = gkr_pk_netscape_trust_get_bool_attribute;
-	parent_class->get_ulong_attribute = gkr_pk_netscape_trust_get_ulong_attribute;
-	parent_class->get_data_attribute = gkr_pk_netscape_trust_get_data_attribute;
+	parent_class->get_attribute = gkr_pk_netscape_trust_get_attribute;
 	
 	gobject_class->get_property = gkr_pk_netscape_trust_get_property;
 	gobject_class->set_property = gkr_pk_netscape_trust_set_property;

Modified: trunk/pk/gkr-pk-object-manager.c
==============================================================================
--- trunk/pk/gkr-pk-object-manager.c	(original)
+++ trunk/pk/gkr-pk-object-manager.c	Mon Jan 14 01:22:17 2008
@@ -85,14 +85,13 @@
 }
 
 static void
-add_object_for_unique (GkrPkObjectManager *objmgr, gkrconstunique unique, GkrPkObject *object)
+add_object (GkrPkObjectManager *objmgr, GkrPkObject *object)
 {
  	GkrPkObjectManagerPrivate *pv = GKR_PK_OBJECT_MANAGER_GET_PRIVATE (objmgr);
 	gpointer k;
 	
-	g_assert (unique);
-	g_assert (object);
-	g_assert (gkr_unique_equals (object->unique, unique));
+	g_assert (GKR_IS_PK_OBJECT (object));
+	g_assert (object->unique);
 	g_assert (object->manager == NULL);
 	
 	if (!object->handle) {
@@ -108,9 +107,11 @@
 	g_assert (g_hash_table_lookup (pv->object_by_handle, k) == NULL); 
 	g_hash_table_replace (pv->object_by_handle, k, object);
 	
-	/* Mapping of objects by index key */
+	/* 
+	 * Mapping of objects by unique key. There may be multiple objects
+	 * with a given unique key.
+	 */
 	g_assert (object->unique);
-	g_assert (g_hash_table_lookup (pv->object_by_unique, object->unique) == NULL); 
 	g_hash_table_replace (pv->object_by_unique, object->unique, object);
 	
 	/* Note objects is being managed */
@@ -119,27 +120,25 @@
 }
 
 static void
-remove_object_at_unique (GkrPkObjectManager *objmgr, gkrconstunique unique)
+remove_object (GkrPkObjectManager *objmgr, GkrPkObject *object)
 {
  	GkrPkObjectManagerPrivate *pv = GKR_PK_OBJECT_MANAGER_GET_PRIVATE (objmgr);
- 	GkrPkObject *object;
 	gpointer k;
 	
-	g_assert (unique);
-	
-	/* Get the object referred to */
-	object = (GkrPkObject*)g_hash_table_lookup (pv->object_by_unique, unique);
 	g_assert (GKR_IS_PK_OBJECT (object));
 	g_assert (object->manager == objmgr);
-
+	
 	/* Mapping of objects by PKCS#11 'handle' */	
 	k = GUINT_TO_POINTER (object->handle);
 	g_assert (g_hash_table_lookup (pv->object_by_handle, k) == object); 
 	g_hash_table_remove (pv->object_by_handle, k);
 	
-	/* Mapping of objects by index key */
-	g_assert (gkr_unique_equals (object->unique, unique));
-	g_hash_table_remove (pv->object_by_unique, unique); 
+	/* 
+	 * Mapping of objects by unique key. There may be multiple objects
+	 * with a given unique, so just remove if it matches this one.
+	 */
+	if (g_hash_table_lookup (pv->object_by_unique, object->unique) == object)
+		g_hash_table_remove (pv->object_by_unique, object->unique); 
 	
 	/* Release object management */		
 	objmgr->objects = g_list_remove (objmgr->objects, object);
@@ -280,7 +279,7 @@
 	g_return_if_fail (object->manager == NULL);
 	g_return_if_fail (object->unique);
 
-	add_object_for_unique (objmgr, object->unique, object);
+	add_object (objmgr, object);
 }
 
 void
@@ -295,7 +294,7 @@
 	g_return_if_fail (object->manager == objmgr);
 	g_return_if_fail (object->unique);
 
-	remove_object_at_unique (objmgr, object->unique);
+	remove_object (objmgr, object);
 }
 
 GkrPkObject*

Modified: trunk/pk/gkr-pk-object-storage.c
==============================================================================
--- trunk/pk/gkr-pk-object-storage.c	(original)
+++ trunk/pk/gkr-pk-object-storage.c	Mon Jan 14 01:22:17 2008
@@ -714,3 +714,19 @@
 	g_object_unref (obj);
 	return ret;
 }
+
+gboolean
+gkr_pk_object_storage_add (GkrPkObjectStorage *storage, GkrPkObject *obj, 
+                           GError **err)
+{
+	/* TODO: Need to implement */
+	g_return_val_if_reached (FALSE);
+}
+
+gboolean
+gkr_pk_object_storage_remove (GkrPkObjectStorage *storage, GkrPkObject *obj, 
+                              GError **err)
+{
+	/* TODO: Need to implement */
+	g_return_val_if_reached (FALSE);
+}

Modified: trunk/pk/gkr-pk-object-storage.h
==============================================================================
--- trunk/pk/gkr-pk-object-storage.h	(original)
+++ trunk/pk/gkr-pk-object-storage.h	Mon Jan 14 01:22:17 2008
@@ -57,6 +57,12 @@
 gboolean                gkr_pk_object_storage_load_complete      (GkrPkObjectStorage *storage, 
                                                                   GkrPkObject *obj, GError **err);
 
+gboolean                gkr_pk_object_storage_add                (GkrPkObjectStorage *storage,
+                                                                  GkrPkObject *obj, GError **err);
+
+gboolean                gkr_pk_object_storage_remove             (GkrPkObjectStorage *storage,
+                                                                  GkrPkObject *obj, GError **err);
+
 G_END_DECLS
 
 #endif /* __GKR_PK_OBJECT_STORAGE_H__ */

Modified: trunk/pk/gkr-pk-object.c
==============================================================================
--- trunk/pk/gkr-pk-object.c	(original)
+++ trunk/pk/gkr-pk-object.c	Mon Jan 14 01:22:17 2008
@@ -23,9 +23,12 @@
 
 #include "config.h"
 
+#include "gkr-pk-cert.h"
 #include "gkr-pk-index.h"
 #include "gkr-pk-object.h"
 #include "gkr-pk-object-manager.h"
+#include "gkr-pk-privkey.h"
+#include "gkr-pk-pubkey.h"
 #include "gkr-pk-util.h"
 
 #include "common/gkr-location.h"
@@ -73,56 +76,25 @@
 static CK_RV
 lookup_attribute (GkrPkObject *object, CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR *attr)
 {
-	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE(object);
+	GkrPkObjectPrivate *pv = GKR_PK_OBJECT_GET_PRIVATE (object);
 	GkrPkObjectClass *klass;
 	CK_ATTRIBUTE cattr;
 	CK_RV ret = 0;
-	
+
 	*attr = g_hash_table_lookup (pv->attr_cache, GUINT_TO_POINTER (type));
 	if(*attr)
 		return CKR_OK;
 		
 	klass = GKR_PK_OBJECT_GET_CLASS (object);
-		
 	memset (&cattr, 0, sizeof (cattr));
 	cattr.type = type;
 
-	switch (gkr_pk_attribute_data_type (type))
-	{
-	case GKR_PK_DATA_BOOL:
-		if (!klass->get_bool_attribute)
-			return CKR_ATTRIBUTE_TYPE_INVALID;
-		ret = (*klass->get_bool_attribute) (object, &cattr);
-		break;
-		
-	case GKR_PK_DATA_ULONG:
-		if (!klass->get_ulong_attribute)
-			return CKR_ATTRIBUTE_TYPE_INVALID;
-		ret = (*klass->get_ulong_attribute) (object, &cattr);
-		break;
-		
-	case GKR_PK_DATA_BYTES:
-		if (!klass->get_data_attribute)
-			return CKR_ATTRIBUTE_TYPE_INVALID;
-		ret = (*klass->get_data_attribute) (object, &cattr);
-		break;
-		
-	case GKR_PK_DATA_DATE:
-		if (!klass->get_date_attribute)
-			return CKR_ATTRIBUTE_TYPE_INVALID;
-		ret = (*klass->get_date_attribute) (object, &cattr);
-		break;
-				
-	case GKR_PK_DATA_UNKNOWN:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-		
-	default:
-		g_assert_not_reached ();
-		break;
-	};
+	/* Ask derived class for attribute */
+	if (!klass->get_attribute)
+		g_return_val_if_reached (CKR_ATTRIBUTE_TYPE_INVALID);
+	ret = (*klass->get_attribute) (object, &cattr);
 
-	if (ret != CKR_OK)
-	{
+	if (ret != CKR_OK) {
 		/* Shouldn't be returning these */
 		g_assert (ret != CKR_BUFFER_TOO_SMALL);
 		return ret;
@@ -177,6 +149,71 @@
 	return obj;
 }
 
+static CK_RV
+gkr_pk_object_get_attribute_common (GkrPkObject *obj, CK_ATTRIBUTE_PTR attr)
+{
+	CK_OBJECT_CLASS cls;
+	gchar *label;
+
+	switch (attr->type) {
+	case CKA_LABEL:
+		label = gkr_pk_object_get_label (obj);
+		if (!label && obj->location)
+			label = gkr_location_to_display (obj->location);
+		if (!label)
+			label = g_strdup ("");
+		gkr_pk_attribute_set_string (attr, label);
+		g_free (label);
+		return CKR_OK;
+	
+	case CKA_TOKEN:
+		gkr_pk_attribute_set_boolean (attr, 
+			(obj->handle & GKR_PK_OBJECT_IS_PERMANENT) == GKR_PK_OBJECT_IS_PERMANENT);
+		return CKR_OK;
+		
+	case CKA_PRIVATE:
+		gkr_pk_attribute_set_boolean (attr, 
+			(gkr_pk_object_get_ulong (obj, CKA_CLASS, &cls) == CKR_OK &&
+			 gkc_pk_class_is_private (cls)));
+		return CKR_OK; 
+
+	case CKA_MODIFIABLE:
+		/* TODO: Does this need to check somewhere? */
+		gkr_pk_attribute_set_boolean (attr, CK_TRUE);
+		return CKR_OK;
+		
+	default:
+		return CKR_ATTRIBUTE_TYPE_INVALID;
+	};
+}
+
+static CK_RV
+gkr_pk_object_set_attribute_common (GkrPkObject *obj, CK_ATTRIBUTE_PTR attr)
+{
+	gchar *label;
+	
+	switch (attr->type) {
+	case CKA_LABEL:
+		if (!attr->pValue && attr->ulValueLen)
+			return CKR_ATTRIBUTE_VALUE_INVALID;
+		label = g_strndup (attr->pValue, attr->ulValueLen);
+		gkr_pk_object_set_label (obj, label);
+		g_free (label);
+		return CKR_OK;
+		
+	case CKA_TOKEN:
+	case CKA_PRIVATE:
+	case CKA_MODIFIABLE:
+		return CKR_ATTRIBUTE_READ_ONLY;
+		
+	case CKA_CLASS:
+		return CKR_ATTRIBUTE_READ_ONLY;
+		
+	default:
+		return CKR_ATTRIBUTE_TYPE_INVALID;	
+	};
+}
+
 static void
 gkr_pk_object_get_property (GObject *obj, guint prop_id, GValue *value, 
                              GParamSpec *pspec)
@@ -198,7 +235,7 @@
 		g_value_set_string (value, pv->orig_label);
 		break;
 	case PROP_LABEL:
-		g_value_set_string (value, gkr_pk_object_get_label (xobj));
+		g_value_take_string (value, gkr_pk_object_get_label (xobj));
 		break;
 	}
 }
@@ -265,6 +302,9 @@
 	gobject_class->get_property = gkr_pk_object_get_property;
 	gobject_class->set_property = gkr_pk_object_set_property;
 	gobject_class->finalize = gkr_pk_object_finalize;
+	
+	klass->get_attribute = gkr_pk_object_get_attribute_common;
+	klass->set_attribute = gkr_pk_object_set_attribute_common;
 
 	g_type_class_add_private (gobject_class, sizeof (GkrPkObjectPrivate));
 	
@@ -293,6 +333,61 @@
  * PUBLIC 
  */
  
+CK_RV
+gkr_pk_object_create (GkrPkObjectManager *manager, 
+                      GArray *attrs, GkrPkObject **object)
+{
+	CK_ATTRIBUTE_PTR attr;
+	CK_OBJECT_CLASS cls;
+	CK_RV ret;
+	guint i;
+	
+	if (!gkr_pk_attributes_ulong (attrs, CKA_CLASS, &cls))
+		return CKR_TEMPLATE_INCOMPLETE;
+	gkr_pk_attributes_consume (attrs, CKA_CLASS, -1);
+	
+	switch (cls) {
+	case CKO_PUBLIC_KEY:
+		ret = gkr_pk_pubkey_create (manager, attrs, object);
+		break;
+	case CKO_PRIVATE_KEY:
+		ret = gkr_pk_privkey_create (manager, attrs, object);
+		break;
+	case CKO_CERTIFICATE:
+		ret = gkr_pk_cert_create (manager, attrs, object);
+		break;
+	default:
+		/* TODO: What's a better error code here? */
+		return CKR_FUNCTION_NOT_SUPPORTED;
+	};
+	
+	if (ret != CKR_OK)
+		return ret;
+		
+	g_return_val_if_fail (*object != NULL, CKR_GENERAL_ERROR);
+	
+	/* 
+	 * Check that all the remaining attributes are either already
+	 * set or are settable 
+	 */
+	for (i = 0; i < attrs->len; ++i) {
+		attr = &(g_array_index (attrs, CK_ATTRIBUTE, i));
+		if (!gkr_pk_attribute_is_consumed (attr)) {
+			ret = gkr_pk_object_set_attribute (*object, attr);
+			if (ret != CKR_OK)
+				break;
+		}  
+	} 	
+	
+	/* Unsuccessful so free the object */
+	if (ret != CKR_OK) {
+		g_object_unref (*object);
+		*object = NULL;
+	}
+	
+	return ret;
+}
+
 void
 gkr_pk_object_flush (GkrPkObject *object)
 {
@@ -440,6 +535,98 @@
 	return ret;
 }
 
+CK_RV
+gkr_pk_object_set_attribute (GkrPkObject *object, CK_ATTRIBUTE_PTR attr)
+{
+	GkrPkObjectClass *klass;
+	CK_ATTRIBUTE_PTR cattr;
+	CK_BBOOL bvalue;
+	CK_ULONG nvalue;
+	gboolean found;
+	CK_RV ret = 0;
+	
+	/* Get the current value for this attribute */ 
+	found = (lookup_attribute (object, attr->type, &cattr) == CKR_OK);
+	if (found) {
+		
+		/* Compare it with the the new one, and ignore if equal */
+		if (gkr_pk_attribute_equal (attr, cattr))
+			return CKR_OK;
+	}
+
+	klass = GKR_PK_OBJECT_GET_CLASS (object);
+
+	/* A quick early check of the values */	
+	switch (gkr_pk_attribute_data_type (attr->type))
+	{
+	case GKR_PK_DATA_BOOL:
+		if (!gkr_pk_attribute_get_boolean (attr, &bvalue))
+			return CKR_ATTRIBUTE_VALUE_INVALID;
+		break;
+		
+	case GKR_PK_DATA_ULONG:
+		if (!gkr_pk_attribute_get_ulong (attr, &nvalue))
+			return CKR_ATTRIBUTE_VALUE_INVALID;
+		break;
+
+	case GKR_PK_DATA_BYTES:
+		break;
+		
+	case GKR_PK_DATA_UNKNOWN:
+		return CKR_ATTRIBUTE_TYPE_INVALID;
+		
+	default:
+		g_assert_not_reached ();
+		break;
+	};
+
+	/* If we didn't call above, then set via main method */
+	if (klass->set_attribute)
+		ret = (*klass->set_attribute) (object, attr);
+	else
+		ret = CKR_ATTRIBUTE_TYPE_INVALID; 
+	
+	/* 
+	 * If a method and value was found for reading, but no method
+	 * was found for writing, then this must be a readonly. 
+	 */
+	if (ret == CKR_ATTRIBUTE_TYPE_INVALID && found)
+		ret = CKR_ATTRIBUTE_READ_ONLY;
+
+	return ret;
+}
+                                                    
+CK_RV
+gkr_pk_object_set_ulong (GkrPkObject *object, CK_ATTRIBUTE_TYPE type, CK_ULONG value)
+{
+	CK_ATTRIBUTE attr = { type, &value, sizeof (value) }; 
+	return gkr_pk_object_set_attribute (object, &attr);
+}
+
+CK_RV
+gkr_pk_object_set_bool (GkrPkObject *object, CK_ATTRIBUTE_TYPE type, CK_BBOOL value)
+{
+	CK_ATTRIBUTE attr = { type, &value, sizeof (value) }; 
+	return gkr_pk_object_set_attribute (object, &attr);
+}
+                                                    
+CK_RV
+gkr_pk_object_set_attributes (GkrPkObject *object, GArray *attrs)
+{
+	CK_ATTRIBUTE_PTR attr;
+	CK_RV ret = CKR_OK;
+	guint i;
+	
+	for (i = 0; i < attrs->len; ++i) {
+		attr = &(g_array_index (attrs, CK_ATTRIBUTE, i));
+		ret = gkr_pk_object_set_attribute (object, attr);
+		if (ret != CKR_OK)
+			break;  
+	} 
+	
+	return ret;
+}
+
 gchar*
 gkr_pk_object_get_label (GkrPkObject *xobj)
 {

Modified: trunk/pk/gkr-pk-object.h
==============================================================================
--- trunk/pk/gkr-pk-object.h	(original)
+++ trunk/pk/gkr-pk-object.h	Mon Jan 14 01:22:17 2008
@@ -62,14 +62,16 @@
 struct _GkrPkObjectClass {
 	GObjectClass parent_class;
 
-	CK_RV (*get_bool_attribute) (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr);
-	CK_RV (*get_ulong_attribute) (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr);
-	CK_RV (*get_data_attribute) (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr);
-	CK_RV (*get_date_attribute) (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr);
+	/* The attribute getter and setter */
+	CK_RV (*get_attribute) (GkrPkObject *obj, CK_ATTRIBUTE_PTR attr);
+	CK_RV (*set_attribute) (GkrPkObject *obj, CK_ATTRIBUTE_PTR attr); 
 };
 
 GType               gkr_pk_object_get_type         (void) G_GNUC_CONST;
 
+CK_RV               gkr_pk_object_create           (GkrPkObjectManager *manager, 
+                                                    GArray *attrs, GkrPkObject **object);
+                                                    
 void                gkr_pk_object_refresh          (GkrPkObject *object);
 
 void                gkr_pk_object_flush            (GkrPkObject *object);
@@ -98,6 +100,20 @@
 CK_RV               gkr_pk_object_get_attributes   (GkrPkObject *object,
                                                     GArray *attrs);
 
+CK_RV               gkr_pk_object_set_attribute    (GkrPkObject *object,
+                                                    CK_ATTRIBUTE_PTR attr);
+                                                    
+CK_RV               gkr_pk_object_set_ulong        (GkrPkObject *object, 
+                                                    CK_ATTRIBUTE_TYPE type,
+                                                    CK_ULONG value);
+
+CK_RV               gkr_pk_object_set_bool         (GkrPkObject *object, 
+                                                    CK_ATTRIBUTE_TYPE type,
+                                                    CK_BBOOL value);
+                                                    
+CK_RV               gkr_pk_object_set_attributes   (GkrPkObject *object, 
+                                                    GArray *attrs);
+
 gchar*              gkr_pk_object_get_label        (GkrPkObject *object);
 
 void                gkr_pk_object_set_label        (GkrPkObject *object, 

Modified: trunk/pk/gkr-pk-privkey.c
==============================================================================
--- trunk/pk/gkr-pk-privkey.c	(original)
+++ trunk/pk/gkr-pk-privkey.c	Mon Jan 14 01:22:17 2008
@@ -157,6 +157,110 @@
 	return key->priv->pubkey;
 }
 
+static CK_RV
+create_rsa_private (GArray *attrs, gcry_sexp_t *skey)
+{
+	gcry_error_t gcry;
+	gcry_mpi_t n = NULL;
+	gcry_mpi_t e = NULL;
+	gcry_mpi_t d = NULL;
+	gcry_mpi_t p = NULL;
+	gcry_mpi_t q = NULL;
+	gcry_mpi_t u = NULL;
+	CK_RV ret;
+	
+	if (!gkr_pk_attributes_mpi (attrs, CKA_MODULUS, &n) ||
+	    !gkr_pk_attributes_mpi (attrs, CKA_PUBLIC_EXPONENT, &e) || 
+	    !gkr_pk_attributes_mpi (attrs, CKA_PRIVATE_EXPONENT, &d) || 
+	    !gkr_pk_attributes_mpi (attrs, CKA_PRIME_1, &p) || 
+	    !gkr_pk_attributes_mpi (attrs, CKA_PRIME_2, &q)) {
+	    	ret = CKR_TEMPLATE_INCOMPLETE;
+	    	goto done;
+	}		
+	
+	/* Fix up the incoming key so gcrypt likes it */    	
+	if (gcry_mpi_cmp (p, q) > 0)
+		gcry_mpi_swap (p, q);
+
+	/* Compute U.  */
+	u = gcry_mpi_snew (gcry_mpi_get_nbits (n));
+	gcry_mpi_invm (u, p, q);
+	
+	gcry = gcry_sexp_build (skey, NULL, 
+	                        "(private-key (rsa (n %m) (e %m) (d %m) (p %m) (q %m) (u %m)))", 
+	                        n, e, d, p, q, u);
+
+	/* TODO: We should be mapping better return codes */
+	if (gcry != 0) {
+		g_message ("couldn't create RSA key from passed attributes");
+		ret = CKR_GENERAL_ERROR;
+		goto done;
+	}
+	
+	gkr_pk_attributes_consume (attrs, CKA_MODULUS, CKA_PUBLIC_EXPONENT, 
+	                           CKA_PRIVATE_EXPONENT, CKA_PRIME_1, CKA_PRIME_2, 
+	                           CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT, -1);
+	ret = CKR_OK;
+
+done:
+	gcry_mpi_release (n);
+	gcry_mpi_release (e);
+	gcry_mpi_release (d);
+	gcry_mpi_release (p);
+	gcry_mpi_release (q);
+	gcry_mpi_release (u);
+	return ret;	
+}
+
+static CK_RV
+create_dsa_private (GArray *attrs, gcry_sexp_t *skey)
+{
+	gcry_error_t gcry;
+	gcry_mpi_t p = NULL;
+	gcry_mpi_t q = NULL;
+	gcry_mpi_t g = NULL;
+	gcry_mpi_t y = NULL;
+	gcry_mpi_t value = NULL;
+	CK_RV ret;
+	
+	if (!gkr_pk_attributes_mpi (attrs, CKA_PRIME, &p) ||
+	    !gkr_pk_attributes_mpi (attrs, CKA_SUBPRIME, &q) || 
+	    !gkr_pk_attributes_mpi (attrs, CKA_BASE, &g) ||
+	    !gkr_pk_attributes_mpi (attrs, CKA_VALUE, &value)) {
+	    	ret = CKR_TEMPLATE_INCOMPLETE;
+	    	goto done;
+	}
+	
+	/* Calculate the public part from the private */
+	y = gcry_mpi_snew (gcry_mpi_get_nbits (value));
+	g_return_val_if_fail (y, CKR_GENERAL_ERROR);
+  	gcry_mpi_powm (y, g, value, p);
+
+	gcry = gcry_sexp_build (skey, NULL, 
+	                        "(private-key (dsa (p %m) (q %m) (g %m) (y %m) (x %m)))",
+	                        p, q, g, y, value);
+
+	/* TODO: We should be mapping better return codes */
+	if (gcry != 0) {
+		g_message ("couldn't create DSA key from passed attributes");
+		ret = CKR_GENERAL_ERROR;
+		goto done;
+	}
+
+	gkr_pk_attributes_consume (attrs, CKA_PRIME, CKA_SUBPRIME, 
+	                           CKA_BASE, CKA_VALUE, -1);
+	ret = CKR_OK;
+
+done:
+	gcry_mpi_release (p);
+	gcry_mpi_release (q);
+	gcry_mpi_release (g);
+	gcry_mpi_release (y);
+	gcry_mpi_release (value);
+	return ret;
+}
+
+
 static void
 initialize_from_key (GkrPkPrivkey *key)
 {
@@ -282,11 +386,14 @@
 	}
 }
 
-static CK_RV 
-gkr_pk_privkey_get_bool_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
+static CK_RV
+gkr_pk_privkey_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
 {
+	GkrPkPrivkey *key = GKR_PK_PRIVKEY (obj);
+	gkrconstunique keyid;
 	GQuark *quarks;
-	gboolean val;
+	guchar *value;
+	gsize len;
 	
 	switch (attr->type)
 	{
@@ -295,104 +402,48 @@
 	case CKA_SENSITIVE:
 	case CKA_SIGN:
 	case CKA_SIGN_RECOVER:
-	case CKA_TOKEN:
 	case CKA_WRAP_WITH_TRUSTED:
-		val = TRUE;
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_TRUE);
+		return CKR_OK;
 	
 	case CKA_DERIVE:
 	case CKA_EXTRACTABLE:
-	case CKA_MODIFIABLE:
 	case CKA_UNWRAP:
-		val = FALSE; 
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 
 	case CKA_GNOME_PURPOSE_SSH_AUTH:
 		quarks = gkr_pk_index_get_quarks (obj, "purposes");
-		val = quarks && gkr_pk_index_quarks_has (quarks, SSH_AUTHENTICATION);
+		gkr_pk_attribute_set_boolean (attr, quarks && 
+				gkr_pk_index_quarks_has (quarks, SSH_AUTHENTICATION));
 		gkr_pk_index_quarks_free (quarks);
-		break;
+		return CKR_OK;
 
 	/* TODO: Perhaps we can detect this in some way */
 	case CKA_ALWAYS_SENSITIVE:
 	case CKA_LOCAL:
 	case CKA_NEVER_EXTRACTABLE:
-		val = FALSE;	
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 		
 	/* TODO: We may be able to detect this for certain keys */
 	case CKA_ALWAYS_AUTHENTICATE:
-		val = FALSE;
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 		
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_boolean (attr, val);
-	return CKR_OK;
-}
-
-static CK_RV 
-gkr_pk_privkey_get_ulong_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkPrivkey *key = GKR_PK_PRIVKEY (obj);
-	gulong val;
-	
-	switch (attr->type)
-	{
 	case CKA_CLASS:
-		val = CKO_PRIVATE_KEY;
-		break;
+		gkr_pk_attribute_set_ulong (attr, CKO_PRIVATE_KEY);
+		return CKR_OK;
 		
 	case CKA_KEY_TYPE:
-		if (attribute_from_public (key, attr) == CKR_OK)
-			return CKR_OK;
-		val = CK_UNAVAILABLE_INFORMATION;
-		break;
+		if (attribute_from_public (key, attr) != CKR_OK)
+			gkr_pk_attribute_set_ulong (attr, CK_UNAVAILABLE_INFORMATION);
+		return CKR_OK;
 		
 	/* TODO: Once we can generate keys, this should change */
 	case CKA_KEY_GEN_MECHANISM:
-		val = CK_UNAVAILABLE_INFORMATION;
-		break;
-		
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_ulong (attr, val);
-	return CKR_OK;
-}
-
-static CK_RV
-gkr_pk_privkey_get_data_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkPrivkey *key = GKR_PK_PRIVKEY (obj);
-	gkrconstunique keyid;
-	gchar *label;
-	guchar *value;
-	gsize len;
-	CK_RV ret;
-	
-	switch (attr->type)
-	{
-	case CKA_LABEL:
-		g_object_get (obj, "label", &label, NULL);
-		if (label) {
-			gkr_pk_attribute_set_string (attr, label);
-			g_free (label);
-			return CKR_OK;
-		}
-		
-		ret = attribute_from_certificate (key, attr);
-		if (ret == CKR_ATTRIBUTE_TYPE_INVALID) {
-			label = gkr_location_to_display (obj->location);
-			gkr_pk_attribute_set_string (attr, label);
-			g_free (label);
-			ret = CKR_OK;
-		}
-		
-		return ret;
+		gkr_pk_attribute_set_ulong (attr, CK_UNAVAILABLE_INFORMATION);
+		return CKR_OK;
 		
 	case CKA_ID:
 		keyid = gkr_pk_privkey_get_keyid (key);
@@ -440,26 +491,16 @@
 	case CKA_UNWRAP_TEMPLATE:
 		return CKR_ATTRIBUTE_TYPE_INVALID;
 		
-	default:
-		break;
-	};
-
-	return CKR_ATTRIBUTE_TYPE_INVALID;
-}
-
-static CK_RV 
-gkr_pk_privkey_get_date_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	switch (attr->type)
-	{
 	/* We don't support these */
 	case CKA_START_DATE:
 	case CKA_END_DATE:
 		return CKR_ATTRIBUTE_TYPE_INVALID;
-	
+
 	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
+		break;
 	};
+
+	return GKR_PK_OBJECT_CLASS (gkr_pk_privkey_parent_class)->get_attribute (obj, attr);
 }
 
 static void
@@ -500,10 +541,7 @@
 	gkr_pk_privkey_parent_class = g_type_class_peek_parent (klass);
 	
 	parent_class = GKR_PK_OBJECT_CLASS (klass);
-	parent_class->get_bool_attribute = gkr_pk_privkey_get_bool_attribute;
-	parent_class->get_ulong_attribute = gkr_pk_privkey_get_ulong_attribute;
-	parent_class->get_data_attribute = gkr_pk_privkey_get_data_attribute;
-	parent_class->get_date_attribute = gkr_pk_privkey_get_date_attribute;
+	parent_class->get_attribute = gkr_pk_privkey_get_attribute;
 	
 	gobject_class = (GObjectClass*)klass;
 	gobject_class->get_property = gkr_pk_privkey_get_property;
@@ -541,6 +579,44 @@
 	return key;
 }
 
+CK_RV
+gkr_pk_privkey_create (GkrPkObjectManager* manager, GArray* array, 
+                       GkrPkObject **object)
+{
+ 	CK_KEY_TYPE type;
+ 	gcry_sexp_t sexp;
+ 	CK_RV ret;
+ 	
+	g_return_val_if_fail (GKR_IS_PK_OBJECT_MANAGER (manager), CKR_GENERAL_ERROR);
+	g_return_val_if_fail (array, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (object, CKR_GENERAL_ERROR);
+	
+	*object = NULL;
+	
+	if (!gkr_pk_attributes_ulong (array, CKA_KEY_TYPE, &type))
+ 		return CKR_TEMPLATE_INCOMPLETE;
+ 	gkr_pk_attributes_consume (array, CKA_KEY_TYPE, -1);
+
+ 	switch (type) {
+	case CKK_RSA:
+		ret = create_rsa_private (array, &sexp);
+		break;
+	case CKK_DSA:
+		ret = create_dsa_private (array, &sexp);
+		break;
+	default:
+		return CKR_ATTRIBUTE_VALUE_INVALID;
+ 	};
+
+	if (ret != CKR_OK)
+		return ret;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);	
+	*object = gkr_pk_privkey_new (manager, 0, sexp);
+	
+	return CKR_OK;
+}
+
 gkrconstunique
 gkr_pk_privkey_get_keyid (GkrPkPrivkey *key)
 {

Modified: trunk/pk/gkr-pk-privkey.h
==============================================================================
--- trunk/pk/gkr-pk-privkey.h	(original)
+++ trunk/pk/gkr-pk-privkey.h	Mon Jan 14 01:22:17 2008
@@ -55,8 +55,12 @@
 
 GType               gkr_pk_privkey_get_type           (void) G_GNUC_CONST;
 
-GkrPkObject*        gkr_pk_privkey_new                (GkrPkObjectManager *mgr, GQuark location, gcry_sexp_t skey);
+GkrPkObject*        gkr_pk_privkey_new                (GkrPkObjectManager *mgr, 
+                                                       GQuark location, gcry_sexp_t skey);
 
+CK_RV               gkr_pk_privkey_create             (GkrPkObjectManager* manager, 
+                                                       GArray* array, GkrPkObject **object);
+                                                       
 gkrconstunique      gkr_pk_privkey_get_keyid          (GkrPkPrivkey *pkey);
 
 gkrunique           gkr_pk_privkey_make_keyid         (gcry_sexp_t skey);

Modified: trunk/pk/gkr-pk-pubkey.c
==============================================================================
--- trunk/pk/gkr-pk-pubkey.c	(original)
+++ trunk/pk/gkr-pk-pubkey.c	Mon Jan 14 01:22:17 2008
@@ -128,6 +128,80 @@
 }
 
 static CK_RV
+create_rsa_public (GArray *attrs, gcry_sexp_t *skey)
+{
+	gcry_error_t gcry;
+	gcry_mpi_t n = NULL;
+	gcry_mpi_t e = NULL;
+	CK_RV ret;
+	
+	if (!gkr_pk_attributes_mpi (attrs, CKA_MODULUS, &n) ||
+	    !gkr_pk_attributes_mpi (attrs, CKA_PUBLIC_EXPONENT, &e)) {
+	    	ret = CKR_TEMPLATE_INCOMPLETE;
+	    	goto done;
+	}		
+	
+	gcry = gcry_sexp_build (skey, NULL, 
+	                        "(public-key (rsa (n %m) (e %m)))", n, e);
+
+	/* TODO: We should be mapping better return codes */
+	if (gcry != 0) {
+		g_message ("couldn't create RSA key from passed attributes");
+		ret = CKR_GENERAL_ERROR;
+		goto done;
+	}
+	
+	gkr_pk_attributes_consume (attrs, CKA_MODULUS, CKA_PUBLIC_EXPONENT, -1);
+	ret = CKR_OK;
+
+done:
+	gcry_mpi_release (n);
+	gcry_mpi_release (e);
+	return ret;	
+}
+
+static CK_RV
+create_dsa_public (GArray *attrs, gcry_sexp_t *skey)
+{
+	gcry_error_t gcry;
+	gcry_mpi_t p = NULL;
+	gcry_mpi_t q = NULL;
+	gcry_mpi_t g = NULL;
+	gcry_mpi_t value = NULL;
+	CK_RV ret;
+	
+	if (!gkr_pk_attributes_mpi (attrs, CKA_PRIME, &p) ||
+	    !gkr_pk_attributes_mpi (attrs, CKA_SUBPRIME, &q) || 
+	    !gkr_pk_attributes_mpi (attrs, CKA_BASE, &g) ||
+	    !gkr_pk_attributes_mpi (attrs, CKA_VALUE, &value)) {
+	    	ret = CKR_TEMPLATE_INCOMPLETE;
+	    	goto done;
+	}
+	    
+	gcry = gcry_sexp_build (skey, NULL, 
+	                        "(public-key (dsa (p %m) (q %m) (g %m) (y %m)))",
+	                        p, q, g, value);	    		
+
+	/* TODO: We should be mapping better return codes */
+	if (gcry != 0) {
+		g_message ("couldn't create DSA key from passed attributes");
+		ret = CKR_GENERAL_ERROR;
+		goto done;
+	}
+	
+	gkr_pk_attributes_consume (attrs, CKA_PRIME, CKA_SUBPRIME, 
+	                           CKA_BASE, CKA_VALUE, -1);
+	ret = CKR_OK;
+	
+done:
+	gcry_mpi_release (p);
+	gcry_mpi_release (q);
+	gcry_mpi_release (g);
+	gcry_mpi_release (value);
+	return ret;
+}
+
+static CK_RV
 attribute_from_related (GkrPkPubkey *key, GType type, CK_ATTRIBUTE_PTR attr)
 {
 	GkrPkObject *crt, *obj;
@@ -230,78 +304,60 @@
 	}
 }
 
-static CK_RV 
-gkr_pk_pubkey_get_bool_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
+static CK_RV
+gkr_pk_pubkey_get_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
 {
-	gboolean val;
+	GkrPkPubkey *key = GKR_PK_PUBKEY (obj);
+	gcry_mpi_t mpi;
+	CK_RV ret;
 	
 	switch (attr->type)
 	{
-	case CKA_ALWAYS_AUTHENTICATE:
 	case CKA_ENCRYPT:
 	case CKA_EXTRACTABLE:
-	case CKA_TOKEN:
 	case CKA_VERIFY:
 	case CKA_VERIFY_RECOVER:
-		val = TRUE;
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_TRUE);
+		return CKR_OK;
 	
+	case CKA_ALWAYS_AUTHENTICATE:
 	case CKA_DERIVE:
-	case CKA_MODIFIABLE:
 	case CKA_PRIVATE:
 	case CKA_SENSITIVE:
 	case CKA_WRAP:
 	case CKA_WRAP_WITH_TRUSTED:
-		val = FALSE;
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 		
 	/* TODO: Use our definition of trusted */
 	case CKA_TRUSTED:
-		val = FALSE;
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 		
 	/* TODO: Perhaps we can detect this in some way */
 	case CKA_LOCAL:
-		val = FALSE;	
-		break;
+		gkr_pk_attribute_set_boolean (attr, CK_FALSE);
+		return CKR_OK;
 		
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_boolean (attr, val);
-	return CKR_OK;
-}
-
-static CK_RV 
-gkr_pk_pubkey_get_ulong_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkPubkey *key = GKR_PK_PUBKEY (obj);
-	gcry_mpi_t mpi;
-	gboolean ret;
-	gulong val;
-	
-	switch (attr->type)
-	{
 	case CKA_CLASS:
-		val = CKO_PUBLIC_KEY;
-		break;
+		gkr_pk_attribute_set_ulong (attr, CKO_PUBLIC_KEY);
+		return CKR_OK;
 		
 	case CKA_KEY_TYPE:
 		if (!load_public_key (key))
 			return CKR_GENERAL_ERROR;
 		switch (key->pub->algorithm) {
 		case GCRY_PK_RSA:
-			val = CKK_RSA;
+			gkr_pk_attribute_set_ulong (attr, CKK_RSA);
 			break;
 		case GCRY_PK_DSA:
-			val = CKK_DSA;
+			gkr_pk_attribute_set_ulong (attr, CKK_DSA);
 			break;
 		default:
 			g_return_val_if_reached (CKR_GENERAL_ERROR);
 			break;
 		}
-		break;
+		return CKR_OK;
 	
 	case CKA_MODULUS_BITS:
 		if (!load_public_key (key))
@@ -311,38 +367,14 @@
 		g_assert (key->pub->numbers);
 		ret = gkr_crypto_sexp_extract_mpi (key->pub->numbers, &mpi, "n", NULL);
 		g_return_val_if_fail (ret, CKR_GENERAL_ERROR);
-		val = gcry_mpi_get_nbits (mpi);
+		gkr_pk_attribute_set_ulong (attr, gcry_mpi_get_nbits (mpi));
 		gcry_mpi_release (mpi);
-		break;
+		return CKR_OK;
 		
 	/* TODO: Once we can generate keys, this should change */
 	case CKA_KEY_GEN_MECHANISM:
 		return CK_UNAVAILABLE_INFORMATION;
 		
-	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
-	};
-	
-	gkr_pk_attribute_set_ulong (attr, val);
-	return CKR_OK;
-}
-
-static CK_RV
-gkr_pk_pubkey_get_data_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	GkrPkPubkey *key = GKR_PK_PUBKEY (obj);
-	gchar *label;
-	
-	switch (attr->type)
-	{
-	case CKA_LABEL:
-		g_object_get (obj, "label", &label, NULL);
-		if (!label)
-			label = gkr_location_to_display (obj->location);
-		gkr_pk_attribute_set_string (attr, label);
-		g_free (label);
-		return CKR_OK;
-		
 	case CKA_ID:
 		/* Always a SHA-1 hash output buffer */
 		if (!load_public_key (key) || !key->pub->keyid)
@@ -384,26 +416,16 @@
 	case CKA_UNWRAP_TEMPLATE:
 		return CKR_ATTRIBUTE_TYPE_INVALID;
 		
-	default:
-		break;
-	};
-
-	return CKR_ATTRIBUTE_TYPE_INVALID;
-}
-
-static CK_RV 
-gkr_pk_pubkey_get_date_attribute (GkrPkObject* obj, CK_ATTRIBUTE_PTR attr)
-{
-	switch (attr->type)
-	{
 	/* We don't support these */
 	case CKA_START_DATE:
 	case CKA_END_DATE:
 		return CKR_ATTRIBUTE_TYPE_INVALID;
 	
 	default:
-		return CKR_ATTRIBUTE_TYPE_INVALID;
+		break;
 	};
+
+	return GKR_PK_OBJECT_CLASS (gkr_pk_pubkey_parent_class)->get_attribute (obj, attr);
 }
 
 static void
@@ -430,10 +452,7 @@
 	gkr_pk_pubkey_parent_class = g_type_class_peek_parent (klass);
 	
 	parent_class = GKR_PK_OBJECT_CLASS (klass);
-	parent_class->get_bool_attribute = gkr_pk_pubkey_get_bool_attribute;
-	parent_class->get_ulong_attribute = gkr_pk_pubkey_get_ulong_attribute;
-	parent_class->get_data_attribute = gkr_pk_pubkey_get_data_attribute;
-	parent_class->get_date_attribute = gkr_pk_pubkey_get_date_attribute;
+	parent_class->get_attribute = gkr_pk_pubkey_get_attribute;
 	
 	gobject_class = (GObjectClass*)klass;
 	gobject_class->get_property = gkr_pk_pubkey_get_property;
@@ -495,6 +514,44 @@
 	return GKR_PK_PUBKEY (pub);
 }
 
+CK_RV
+gkr_pk_pubkey_create (GkrPkObjectManager* manager, GArray* array, 
+                      GkrPkObject **object)
+{
+ 	CK_KEY_TYPE type;
+ 	gcry_sexp_t sexp;
+ 	CK_RV ret;
+ 	
+	g_return_val_if_fail (GKR_IS_PK_OBJECT_MANAGER (manager), CKR_GENERAL_ERROR);
+	g_return_val_if_fail (array, CKR_GENERAL_ERROR);
+	g_return_val_if_fail (object, CKR_GENERAL_ERROR);
+	
+	*object = NULL;
+	
+	if (!gkr_pk_attributes_ulong (array, CKA_KEY_TYPE, &type))
+ 		return CKR_TEMPLATE_INCOMPLETE;
+ 	gkr_pk_attributes_consume (array, CKA_KEY_TYPE, -1);
+
+ 	switch (type) {
+	case CKK_RSA:
+		ret = create_rsa_public (array, &sexp);
+		break;
+	case CKK_DSA:
+		ret = create_dsa_public (array, &sexp);
+		break;
+	default:
+		return CKR_ATTRIBUTE_VALUE_INVALID;
+ 	};
+
+	if (ret != CKR_OK)
+		return ret;
+	
+	g_return_val_if_fail (sexp, CKR_GENERAL_ERROR);	
+	*object = gkr_pk_pubkey_new (manager, 0, sexp);
+	
+	return CKR_OK;
+}
+
 gkrconstunique
 gkr_pk_pubkey_get_keyid (GkrPkPubkey *key)
 {

Modified: trunk/pk/gkr-pk-pubkey.h
==============================================================================
--- trunk/pk/gkr-pk-pubkey.h	(original)
+++ trunk/pk/gkr-pk-pubkey.h	Mon Jan 14 01:22:17 2008
@@ -60,6 +60,9 @@
 GkrPkPubkey*        gkr_pk_pubkey_instance           (GkrPkObjectManager* manager, 
                                                       GQuark location, gcry_sexp_t s_key);
 
+CK_RV               gkr_pk_pubkey_create             (GkrPkObjectManager* manager, 
+                                                      GArray* array, GkrPkObject **object);
+                                                      
 gkrconstunique      gkr_pk_pubkey_get_keyid          (GkrPkPubkey *key);
 
 gcry_sexp_t         gkr_pk_pubkey_get_key            (GkrPkPubkey *key);

Modified: trunk/pk/gkr-pk-util.c
==============================================================================
--- trunk/pk/gkr-pk-util.c	(original)
+++ trunk/pk/gkr-pk-util.c	Mon Jan 14 01:22:17 2008
@@ -153,12 +153,9 @@
 	case CKA_CERT_SHA1_HASH:
 	case CKA_CERT_MD5_HASH:
 	case CKA_GNOME_PURPOSE_OIDS: 
-		return GKR_PK_DATA_BYTES;
-
-	/* CK_DATE data */
 	case CKA_START_DATE:
 	case CKA_END_DATE:
-		return GKR_PK_DATA_DATE;
+		return GKR_PK_DATA_BYTES;
 
 	/* Arrays are nasty */
 	case CKA_WRAP_TEMPLATE:
@@ -188,6 +185,21 @@
 	return nattr;
 }
 
+gboolean
+gkr_pk_attribute_equal (const CK_ATTRIBUTE_PTR one, const CK_ATTRIBUTE_PTR two)
+{
+	if (one->type != two->type)
+		return FALSE;
+
+	if (one->ulValueLen != two->ulValueLen)
+		return FALSE;
+	if (one->pValue == two->pValue)
+		return TRUE;
+	if (!one->pValue || !two->pValue)
+		return FALSE;
+	return memcmp (one->pValue, two->pValue, one->ulValueLen) == 0;	
+}
+
 void
 gkr_pk_attribute_steal (CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR attr)
 {
@@ -238,13 +250,13 @@
 }
 
 void
-gkr_pk_attribute_set_boolean (CK_ATTRIBUTE_PTR attr, gboolean value)
+gkr_pk_attribute_set_boolean (CK_ATTRIBUTE_PTR attr, CK_BBOOL value)
 {
 	g_assert (attr);
 	
 	gkr_pk_attribute_clear (attr);
 	attr->pValue = g_new (CK_BBOOL, 1);
-	*((CK_BBOOL*)attr->pValue) = value ? CK_TRUE : CK_FALSE;
+	*((CK_BBOOL*)attr->pValue) = value;
 	attr->ulValueLen = sizeof (CK_BBOOL);
 }
 
@@ -273,7 +285,7 @@
 	memcpy (date->year, buf, 4);
 	 
 	g_assert (sizeof (date->month) == 2);
-	snprintf ((char*)buf, 3, "%02d", tm.tm_mon);
+	snprintf ((char*)buf, 3, "%02d", tm.tm_mon + 1);
 	memcpy (date->month, buf, 2);
 	
 	g_assert (sizeof (date->day) == 2);
@@ -299,7 +311,7 @@
 }
 
 void
-gkr_pk_attribute_set_ulong (CK_ATTRIBUTE_PTR attr, gulong value)
+gkr_pk_attribute_set_ulong (CK_ATTRIBUTE_PTR attr, CK_ULONG value)
 {
 	g_assert (attr);
 	
@@ -335,6 +347,24 @@
 	g_return_if_fail (gcry == 0);
 }
 
+gboolean
+gkr_pk_attribute_get_boolean (const CK_ATTRIBUTE_PTR attr, CK_BBOOL *value)
+{
+	if (attr->ulValueLen != sizeof (CK_BBOOL))
+		return FALSE;
+	*value = *((const CK_BBOOL*)attr->pValue);
+	return TRUE;
+}
+
+gboolean
+gkr_pk_attribute_get_ulong (const CK_ATTRIBUTE_PTR attr, CK_ULONG *value)
+{
+	if (attr->ulValueLen != sizeof (CK_ULONG))
+		return FALSE;
+	*value = *((const CK_ULONG*)attr->pValue);
+	return TRUE;
+}
+
 void
 gkr_pk_attribute_clear (CK_ATTRIBUTE_PTR attr)
 {
@@ -409,6 +439,13 @@
 }
 
 void
+gkr_pk_attributes_append (GArray *attrs, CK_ATTRIBUTE_PTR attr)
+{
+	g_array_append_vals (attrs, attr, 1);
+	memset (attr, 0, sizeof (*attr));
+}
+
+void
 gkr_pk_attributes_free (GArray *attrs)
 {
 	CK_ATTRIBUTE_PTR attr;
@@ -426,6 +463,50 @@
 }
 
 gboolean
+gkr_pk_attribute_is_consumed (CK_ATTRIBUTE_PTR attr)
+{
+	return attr->type == (CK_ULONG)-1;
+}
+
+void
+gkr_pk_attribute_consume (CK_ATTRIBUTE_PTR attr)
+{
+	attr->type = (CK_ULONG)-1;
+} 
+
+void
+gkr_pk_attributes_consume (GArray *attrs, ...)
+{
+	CK_ATTRIBUTE_TYPE type;
+	CK_ATTRIBUTE_PTR attr;
+	GArray *types;
+	guint i, j;
+	va_list va;
+
+	/* Convert the var args into an array */
+	types = g_array_new (FALSE, TRUE, sizeof (CK_ATTRIBUTE_TYPE));
+	va_start (va, attrs);
+	while ((type = va_arg (va, CK_ATTRIBUTE_TYPE)) != (CK_ULONG)-1)
+		 g_array_append_val (types, type);
+	va_end (va);
+	
+	/* Consume each attribute whose type was in the var args */
+	for (i = 0; i < attrs->len; ++i) {
+		attr = &(g_array_index (attrs, CK_ATTRIBUTE, i));
+		if (gkr_pk_attribute_is_consumed (attr))
+			continue;
+		for (j = 0; j < types->len; ++j) {
+			if (attr->type == g_array_index (types, CK_ATTRIBUTE_TYPE, j)) {
+				gkr_pk_attribute_consume (attr);
+				break;
+			}
+		}
+	}
+	
+	g_array_free (types, TRUE);
+}
+
+gboolean
 gkc_pk_class_is_private (CK_OBJECT_CLASS cls)
 {
 	switch (cls) {

Modified: trunk/pk/gkr-pk-util.h
==============================================================================
--- trunk/pk/gkr-pk-util.h	(original)
+++ trunk/pk/gkr-pk-util.h	Mon Jan 14 01:22:17 2008
@@ -35,7 +35,6 @@
 	GKR_PK_DATA_UNKNOWN = 0,
 	GKR_PK_DATA_BOOL,
 	GKR_PK_DATA_ULONG,
-	GKR_PK_DATA_DATE,
 	GKR_PK_DATA_BYTES
 } GkrPkDataType;
 
@@ -45,6 +44,9 @@
 
 CK_ATTRIBUTE_PTR   gkr_pk_attribute_dup                   (const CK_ATTRIBUTE_PTR attr);
 
+gint               gkr_pk_attribute_equal                 (const CK_ATTRIBUTE_PTR one, 
+                                                           const CK_ATTRIBUTE_PTR two);
+
 void               gkr_pk_attribute_free                  (gpointer attr);
 
 void               gkr_pk_attribute_copy                  (CK_ATTRIBUTE_PTR dest, const CK_ATTRIBUTE_PTR attr);
@@ -62,14 +64,18 @@
 
 void               gkr_pk_attribute_set_unique            (CK_ATTRIBUTE_PTR attr, gkrconstunique uni);
 
-void               gkr_pk_attribute_set_boolean           (CK_ATTRIBUTE_PTR attr, gboolean value);
+void               gkr_pk_attribute_set_boolean           (CK_ATTRIBUTE_PTR attr, CK_BBOOL value);
 
 void               gkr_pk_attribute_set_date              (CK_ATTRIBUTE_PTR attr, time_t time);
 
-void               gkr_pk_attribute_set_ulong             (CK_ATTRIBUTE_PTR attr, gulong value);
+void               gkr_pk_attribute_set_ulong             (CK_ATTRIBUTE_PTR attr, CK_ULONG value);
 
 void               gkr_pk_attribute_set_mpi               (CK_ATTRIBUTE_PTR attr, gcry_mpi_t mpi);
 
+gboolean           gkr_pk_attribute_get_boolean           (const CK_ATTRIBUTE_PTR attr, CK_BBOOL *value);
+
+gboolean           gkr_pk_attribute_get_ulong             (const CK_ATTRIBUTE_PTR attr, CK_ULONG *value);
+ 
 #define            gkr_pk_attributes_new()                (g_array_new (0, 1, sizeof (CK_ATTRIBUTE)))
  
 CK_ATTRIBUTE_PTR   gkr_pk_attributes_find                 (const GArray* attrs, CK_ATTRIBUTE_TYPE type);
@@ -83,8 +89,22 @@
 gboolean           gkr_pk_attributes_mpi                  (const GArray* attrs, CK_ATTRIBUTE_TYPE type, 
                                                            gcry_mpi_t *mpi);
 
+void               gkr_pk_attributes_append               (GArray *attrs, CK_ATTRIBUTE_PTR attr);
+
 void               gkr_pk_attributes_free                 (GArray *attrs);
 
+/* 
+ * 'Consumption' of attributes is used during setting of a set of attributes 
+ * on an object, those that have been handled somewhere are marked consumed. 
+ * This is useful for fallback handling. See gkr_pk_object_set_attribute().
+ */ 
+gboolean           gkr_pk_attribute_is_consumed           (const CK_ATTRIBUTE_PTR attr);
+
+void               gkr_pk_attribute_consume               (CK_ATTRIBUTE_PTR attr);
+
+void               gkr_pk_attributes_consume              (GArray *attrs, ...);
+
+/* Certain object classes are intrinsically private */
 gboolean           gkc_pk_class_is_private                (CK_OBJECT_CLASS cls);
 
 #endif /*GKRPKUTIL_H_*/

Modified: trunk/pk/tests/Makefile.am
==============================================================================
--- trunk/pk/tests/Makefile.am	(original)
+++ trunk/pk/tests/Makefile.am	Mon Jan 14 01:22:17 2008
@@ -2,6 +2,7 @@
 UNIT_AUTO = \
 	unit-test-pk-index.c \
 	unit-test-pk-cert.c \
+	unit-test-pk-key.c \
 	unit-test-pk-netscape-trust.c
 
 UNIT_PROMPT = 

Modified: trunk/pk/tests/check-attribute.c
==============================================================================
--- trunk/pk/tests/check-attribute.c	(original)
+++ trunk/pk/tests/check-attribute.c	Mon Jan 14 01:22:17 2008
@@ -1,6 +1,8 @@
 #ifndef CHECKATTRIBUTE_H_
 #define CHECKATTRIBUTE_H_
 
+#include "pk/gkr-pk-util.h"
+
 static void
 check_attribute (CuTest *cu, GkrPkObject *obj, CK_ATTRIBUTE_TYPE type, 
                  const char* name, gpointer value, gsize len)
@@ -33,5 +35,18 @@
 #define CHECK_BYTE_ATTRIBUTE(cu, obj, type, val, length) \
 	check_attribute (cu, GKR_PK_OBJECT (obj), type, #type, val, length)
 
+#define CHECK_DATE_ATTRIBUTE(cu, obj, type, str) { \
+	CK_ATTRIBUTE test = { 0, NULL, 0 }; \
+	struct tm tm; \
+	time_t time; \
+	GDate *date = g_date_new (); \
+	g_date_set_parse (date, str); \
+	g_date_to_struct_tm (date, &tm); \
+	time = timegm (&tm); \
+	g_date_free (date); \
+	gkr_pk_attribute_set_date (&test, time); \
+	check_attribute (cu, GKR_PK_OBJECT (obj), type, #type, test.pValue, test.ulValueLen); \
+	gkr_pk_attribute_clear (&test); \
+}
 
 #endif /*CHECKATTRIBUTE_H_*/

Added: trunk/pk/tests/test-data/privkey-3.key
==============================================================================
Binary file. No diff available.

Modified: trunk/pk/tests/unit-test-pk-cert.c
==============================================================================
--- trunk/pk/tests/unit-test-pk-cert.c	(original)
+++ trunk/pk/tests/unit-test-pk-cert.c	Mon Jan 14 01:22:17 2008
@@ -82,8 +82,8 @@
 	certificate_1 = gkr_pk_cert_new (manager, 0, asn1);
 	CuAssert (cu, "gkr_pk_cert_new returned bad object", GKR_IS_PK_CERT (certificate_1));
 	
-	if (!g_file_get_contents ("test-data/privkey-1.crt", &data, &n_data, NULL))
-		g_error ("couldn't read privkey-1.crt");
+	if (!g_file_get_contents ("test-data/privkey-1.key", &data, &n_data, NULL))
+		g_error ("couldn't read privkey-1.key");
 	res = gkr_pkix_der_read_private_key ((const guchar*)data, n_data, &sexp);
 	g_assert (res == GKR_PARSE_SUCCESS);
 	
@@ -108,9 +108,15 @@
 		 
 void unit_test_certificate_static (CuTest *cu)
 {
-	CHECK_BOOL_ATTRIBUTE (cu, certificate_1, CKA_TOKEN, CK_TRUE);
+	CHECK_DATE_ATTRIBUTE (cu, certificate_1, CKA_START_DATE, "2007-12-20");
+	CHECK_DATE_ATTRIBUTE (cu, certificate_1, CKA_END_DATE, "2008-01-19");
+	CHECK_BOOL_ATTRIBUTE (cu, certificate_1, CKA_TOKEN, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, certificate_1, CKA_MODIFIABLE, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, certificate_1, CKA_PRIVATE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, certificate_1, CKA_TRUSTED, CK_FALSE);
 	CHECK_ULONG_ATTRIBUTE (cu, certificate_1, CKA_CLASS, CKO_CERTIFICATE);
 	CHECK_ULONG_ATTRIBUTE (cu, certificate_1, CKA_CERTIFICATE_CATEGORY, 0);
+	CHECK_ULONG_ATTRIBUTE (cu, certificate_1, CKA_CERTIFICATE_TYPE, CKC_X_509);
 }
 
 void unit_test_certificate_related (CuTest *cu)
@@ -236,3 +242,85 @@
 	g_strstrip (result);
 	CuAssert (cu, "Returned invalid oid in purpose", g_str_equal (result, "some-purpose"));
 }
+
+void unit_test_certificate_set_attribute (CuTest *cu)
+{
+	GkrPkObject *obj = GKR_PK_OBJECT (certificate_1);
+	CK_RV ret;
+	
+	/* Should succeed if twe change class to itself */
+	ret = gkr_pk_object_set_ulong (obj, CKA_CLASS, CKO_CERTIFICATE);
+	CuAssert (cu, "Should allow setting readonly attribute to same value", ret == CKR_OK);
+
+	/* Shouldn't succeed if twe change class to different */
+	ret = gkr_pk_object_set_ulong (obj, CKA_CLASS, CKO_PRIVATE_KEY);
+	CuAssert (cu, "Shouldn't allow changing readonly attribute", ret == CKR_ATTRIBUTE_READ_ONLY);
+
+	/* Should return readonly when no setter exists on object */
+	ret = gkr_pk_object_set_ulong (obj, CKA_CERTIFICATE_TYPE, CKC_WTLS);
+	CuAssert (cu, "Shouldn't allow changing readonly attribute", ret == CKR_ATTRIBUTE_READ_ONLY);	
+
+	/* Should return invalid when no getter or setter exists on object */
+	ret = gkr_pk_object_set_ulong (obj, CKA_PIXEL_X, 5);
+	CuAssert (cu, "Shouldn't allow changing readonly attribute", ret == CKR_ATTRIBUTE_TYPE_INVALID);	
+
+	/* Should return value invalid when setting wrong type data */
+	ret = gkr_pk_object_set_ulong (obj, CKA_PRIVATE, 5);
+	CuAssert (cu, "Shouldn't allow changing readonly attribute", ret == CKR_ATTRIBUTE_VALUE_INVALID);
+}
+
+void unit_test_certificate_create (CuTest *cu)
+{
+	CK_ATTRIBUTE attr;
+	GkrPkObject *object;
+	GArray *attrs;
+	const guchar *raw;
+	gsize n_raw;
+	CK_RV ret;
+	
+	attrs = gkr_pk_attributes_new ();
+
+	memset (&attr, 0, sizeof (attr));
+	attr.type = CKA_CLASS;
+	gkr_pk_attribute_set_ulong (&attr, CKO_CERTIFICATE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	/* Try to create as with a set of invalid attributes */
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	CuAssert (cu, "Certificate creation succeeded wrongly", ret == CKR_TEMPLATE_INCOMPLETE);
+
+	gkr_pk_attributes_free (attrs);
+	attrs = gkr_pk_attributes_new ();
+	
+	attr.type = CKA_TOKEN; 
+	gkr_pk_attribute_set_boolean (&attr, CK_FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_LABEL;
+	gkr_pk_attribute_set_string (&attr, "A test label");
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_VALUE;
+	raw = gkr_pk_cert_get_raw (certificate_1, &n_raw);
+	gkr_pk_attribute_set_data (&attr, raw, n_raw);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_CLASS;
+	gkr_pk_attribute_set_ulong (&attr, CKO_CERTIFICATE);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_CERTIFICATE_TYPE;
+	gkr_pk_attribute_set_ulong (&attr, CKC_X_509);
+	gkr_pk_attributes_append (attrs, &attr);
+		
+	/* Now try with a proper set of attributes */
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	CuAssert (cu, "Certificate creation failed", ret == CKR_OK);
+	CuAssert (cu, "Returned invalid object", GKR_IS_PK_CERT (object));
+	
+	gkr_pk_attributes_free (attrs);
+	
+	/* Free the certificate */
+	g_object_unref (object);
+	
+}

Added: trunk/pk/tests/unit-test-pk-key.c
==============================================================================
--- (empty file)
+++ trunk/pk/tests/unit-test-pk-key.c	Mon Jan 14 01:22:17 2008
@@ -0,0 +1,379 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-pk-key.c: Test public and private keys
+
+   Copyright (C) 2007 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+
+#include "common/gkr-crypto.h"
+
+#include "pk/gkr-pk-index.h"
+#include "pk/gkr-pk-object.h"
+#include "pk/gkr-pk-object-manager.h"
+#include "pk/gkr-pk-pubkey.h"
+#include "pk/gkr-pk-privkey.h"
+
+#include "pkcs11/pkcs11.h"
+#include "pkcs11/pkcs11g.h"
+
+#include "pkix/gkr-pkix-der.h"
+
+#include <glib.h>
+#include <memory.h>
+#include <gcrypt.h>
+
+/* 
+ * Each test looks like (on one line):
+ *     void unit_test_xxxxx (CuTest* cu)
+ * 
+ * Each setup looks like (on one line):
+ *     void unit_setup_xxxxx (void)
+ * 
+ * Each teardown looks like (on one line):
+ *     void unit_teardown_xxxxx (void)
+ * 
+ * Tests be run in the order specified here.
+ */
+
+static GkrPkObjectManager *manager = NULL;
+
+static GkrPkObject *privkey_1 = NULL;
+static GkrPkObject *privkey_3 = NULL;
+static GkrPkObject *pubkey_1 = NULL;
+
+void unit_setup_keys (void)
+{
+	gkr_crypto_setup ();
+	
+	/* Our own object manager */
+	manager = gkr_pk_object_manager_instance_for_client (1232); 
+}
+
+void unit_test_create_keys (CuTest* cu)
+{
+	GkrParseResult res;
+	gcry_sexp_t sexp;
+	gchar *data;
+	gsize n_data;
+	
+	if (!g_file_get_contents ("test-data/privkey-1.key", &data, &n_data, NULL))
+		g_error ("couldn't read privkey-1.key");
+	res = gkr_pkix_der_read_private_key ((const guchar*)data, n_data, &sexp);
+	g_assert (res == GKR_PARSE_SUCCESS);
+	
+	privkey_1 = gkr_pk_privkey_new (manager, 0, sexp);
+	g_assert (GKR_IS_PK_PRIVKEY (privkey_1));
+	
+	/* Should automatically create a public key */
+	pubkey_1 = GKR_PK_OBJECT (gkr_pk_privkey_get_public (GKR_PK_PRIVKEY (privkey_1)));
+	if (!pubkey_1)
+		g_error ("couldn't get public key");
+		
+	if (!g_file_get_contents ("test-data/privkey-3.key", &data, &n_data, NULL))
+		g_error ("couldn't read privkey-3.key");
+	res = gkr_pkix_der_read_private_key ((const guchar*)data, n_data, &sexp);
+	g_assert (res == GKR_PARSE_SUCCESS);
+	
+	privkey_3 = gkr_pk_privkey_new (manager, 0, sexp);
+	g_assert (GKR_IS_PK_PRIVKEY (privkey_3));
+}
+
+#include "check-attribute.c"
+		 
+void unit_test_privkey_static (CuTest *cu)
+{
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_TOKEN, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_PRIVATE, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_DECRYPT, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_SENSITIVE, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_SIGN, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_SIGN_RECOVER, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_WRAP_WITH_TRUSTED, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_DERIVE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_EXTRACTABLE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_UNWRAP, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_GNOME_PURPOSE_SSH_AUTH, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_ALWAYS_SENSITIVE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_LOCAL, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_NEVER_EXTRACTABLE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, privkey_1, CKA_ALWAYS_AUTHENTICATE, CK_FALSE);
+	
+	CHECK_ULONG_ATTRIBUTE (cu, privkey_1, CKA_CLASS, CKO_PRIVATE_KEY);
+	CHECK_ULONG_ATTRIBUTE (cu, privkey_1, CKA_KEY_TYPE, CKK_RSA);
+	CHECK_ULONG_ATTRIBUTE (cu, privkey_1, CKA_KEY_GEN_MECHANISM, CK_UNAVAILABLE_INFORMATION);
+}
+
+void unit_test_pubkey_static (CuTest *cu)
+{
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_TOKEN, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_PRIVATE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_ENCRYPT, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_SENSITIVE, CK_FALSE);
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_EXTRACTABLE, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_VERIFY, CK_TRUE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_VERIFY_RECOVER, CK_TRUE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_ALWAYS_AUTHENTICATE, CK_FALSE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_DERIVE, CK_FALSE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_WRAP, CK_FALSE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_WRAP_WITH_TRUSTED, CK_FALSE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_TRUSTED, CK_FALSE); 
+	CHECK_BOOL_ATTRIBUTE (cu, pubkey_1, CKA_LOCAL, CK_FALSE); 
+
+	CHECK_ULONG_ATTRIBUTE (cu, pubkey_1, CKA_CLASS, CKO_PUBLIC_KEY);
+	CHECK_ULONG_ATTRIBUTE (cu, pubkey_1, CKA_KEY_TYPE, CKK_RSA);
+	CHECK_ULONG_ATTRIBUTE (cu, pubkey_1, CKA_MODULUS_BITS, 2048);
+}
+
+void unit_test_privkey_related (CuTest *cu)
+{
+	GkrPkObject *obj;
+	gkrconstunique keyid;
+	gkrconstunique pubid;
+	
+	keyid = gkr_pk_privkey_get_keyid (GKR_PK_PRIVKEY (privkey_1));
+	CuAssert (cu, "No key id returned from private key", keyid != NULL);
+	
+	obj = gkr_pk_object_manager_find_by_id (manager, GKR_TYPE_PK_PUBKEY, keyid);
+	CuAssert (cu, "No matching public key object found in manager", GKR_IS_PK_PUBKEY (obj));
+	
+	pubid = gkr_pk_pubkey_get_keyid (GKR_PK_PUBKEY (obj));
+	CuAssert (cu, "No key id returned from public key", pubid != NULL);
+	
+	CuAssert (cu, "private and public key ids do not match", gkr_unique_equals (keyid, pubid));
+}
+
+void unit_test_privkey_rsa_create (CuTest *cu)
+{
+	CK_ATTRIBUTE attr;
+	gcry_sexp_t skey;
+	gcry_mpi_t mpi;
+	GkrPkObject *object;
+	GArray *attrs;
+	CK_RV ret;
+	
+	attrs = gkr_pk_attributes_new ();
+
+	memset (&attr, 0, sizeof (attr));
+	attr.type = CKA_CLASS;
+	gkr_pk_attribute_set_ulong (&attr, CKO_PRIVATE_KEY);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_KEY_TYPE;
+	gkr_pk_attribute_set_ulong (&attr, CKK_RSA);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_MODULUS; 
+	if (gkr_pk_object_get_attribute (privkey_1, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_PUBLIC_EXPONENT; 
+	if (gkr_pk_object_get_attribute (privkey_1, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	skey = gkr_pk_privkey_get_key (GKR_PK_PRIVKEY (privkey_1));
+	CuAssert (cu, "private key has no internal key", skey != NULL);
+
+	attr.type = CKA_PRIVATE_EXPONENT;
+	if (!gkr_crypto_sexp_extract_mpi (skey, &mpi, "private-key", "d", NULL))
+		g_assert (FALSE);
+	gkr_pk_attribute_set_mpi (&attr, mpi);
+	gcry_mpi_release (mpi);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_PRIME_1;
+	if (!gkr_crypto_sexp_extract_mpi (skey, &mpi, "private-key", "p", NULL))
+		g_assert (FALSE);
+	gkr_pk_attribute_set_mpi (&attr, mpi);
+	gcry_mpi_release (mpi);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_PRIME_2;
+	if (!gkr_crypto_sexp_extract_mpi (skey, &mpi, "private-key", "q", NULL))
+		g_assert (FALSE);
+	gkr_pk_attribute_set_mpi (&attr, mpi);
+	gcry_mpi_release (mpi);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	/* Now try with a proper set of attributes */
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	CuAssert (cu, "Private key creation failed", ret == CKR_OK);
+	CuAssert (cu, "Returned invalid object", GKR_IS_PK_PRIVKEY (object));
+	
+	gkr_pk_attributes_free (attrs);
+	
+	/* Free the private key */
+	g_object_unref (object);
+}
+
+void unit_test_pubkey_rsa_create (CuTest *cu)
+{
+	CK_ATTRIBUTE attr;
+	GkrPkObject *object;
+	GArray *attrs;
+	CK_RV ret;
+	
+	attrs = gkr_pk_attributes_new ();
+
+	memset (&attr, 0, sizeof (attr));
+	attr.type = CKA_CLASS;
+	gkr_pk_attribute_set_ulong (&attr, CKO_PUBLIC_KEY);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_KEY_TYPE;
+	gkr_pk_attribute_set_ulong (&attr, CKK_RSA);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_MODULUS; 
+	if (gkr_pk_object_get_attribute (privkey_1, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_PUBLIC_EXPONENT; 
+	if (gkr_pk_object_get_attribute (privkey_1, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	/* Now try with a proper set of attributes */
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	CuAssert (cu, "Public key creation failed", ret == CKR_OK);
+	CuAssert (cu, "Returned invalid object", GKR_IS_PK_PUBKEY (object));
+	
+	gkr_pk_attributes_free (attrs);
+	
+	/* Free the private key */
+	g_object_unref (object);
+}
+
+void unit_test_privkey_dsa_create (CuTest *cu)
+{
+	CK_ATTRIBUTE attr;
+	gcry_sexp_t skey;
+	gcry_mpi_t mpi;
+	GkrPkObject *object;
+	GArray *attrs;
+	CK_RV ret;
+	
+	attrs = gkr_pk_attributes_new ();
+
+	memset (&attr, 0, sizeof (attr));
+	attr.type = CKA_CLASS;
+	gkr_pk_attribute_set_ulong (&attr, CKO_PRIVATE_KEY);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_KEY_TYPE;
+	gkr_pk_attribute_set_ulong (&attr, CKK_DSA);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_PRIME; 
+	if (gkr_pk_object_get_attribute (privkey_3, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_SUBPRIME; 
+	if (gkr_pk_object_get_attribute (privkey_3, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_BASE; 
+	if (gkr_pk_object_get_attribute (privkey_3, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	skey = gkr_pk_privkey_get_key (GKR_PK_PRIVKEY (privkey_3));
+	CuAssert (cu, "private key has no internal key", skey != NULL);
+
+	attr.type = CKA_VALUE;
+	if (!gkr_crypto_sexp_extract_mpi (skey, &mpi, "private-key", "x", NULL))
+		g_assert (FALSE);
+	gkr_pk_attribute_set_mpi (&attr, mpi);
+	gcry_mpi_release (mpi);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	/* Now try with a proper set of attributes */
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	CuAssert (cu, "Private key creation failed", ret == CKR_OK);
+	CuAssert (cu, "Returned invalid object", GKR_IS_PK_PRIVKEY (object));
+	
+	gkr_pk_attributes_free (attrs);
+	
+	/* Free the private key */
+	g_object_unref (object);
+}
+
+void unit_test_pubkey_dsa_create (CuTest *cu)
+{
+	CK_ATTRIBUTE attr;
+	GkrPkObject *object;
+	GArray *attrs;
+	gcry_sexp_t skey;
+	gcry_mpi_t mpi;
+	CK_RV ret;
+	
+	attrs = gkr_pk_attributes_new ();
+
+	memset (&attr, 0, sizeof (attr));
+	attr.type = CKA_CLASS;
+	gkr_pk_attribute_set_ulong (&attr, CKO_PUBLIC_KEY);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_KEY_TYPE;
+	gkr_pk_attribute_set_ulong (&attr, CKK_DSA);
+	gkr_pk_attributes_append (attrs, &attr);
+	
+	attr.type = CKA_PRIME; 
+	if (gkr_pk_object_get_attribute (privkey_3, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_SUBPRIME; 
+	if (gkr_pk_object_get_attribute (privkey_3, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	attr.type = CKA_BASE; 
+	if (gkr_pk_object_get_attribute (privkey_3, &attr) != CKR_OK)
+		g_assert (FALSE);
+	gkr_pk_attributes_append (attrs, &attr);
+
+	skey = gkr_pk_privkey_get_key (GKR_PK_PRIVKEY (privkey_3));
+	CuAssert (cu, "private key has no internal key", skey != NULL);
+
+	attr.type = CKA_VALUE;
+	if (!gkr_crypto_sexp_extract_mpi (skey, &mpi, "private-key", "y", NULL))
+		g_assert (FALSE);
+	gkr_pk_attribute_set_mpi (&attr, mpi);
+	gcry_mpi_release (mpi);
+	gkr_pk_attributes_append (attrs, &attr);
+		
+	/* Now try with a proper set of attributes */
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	CuAssert (cu, "Public key creation failed", ret == CKR_OK);
+	CuAssert (cu, "Returned invalid object", GKR_IS_PK_PUBKEY (object));
+	
+	gkr_pk_attributes_free (attrs);
+	
+	/* Free the private key */
+	g_object_unref (object);
+}

Modified: trunk/pk/tests/unit-test-pk-netscape-trust.c
==============================================================================
--- trunk/pk/tests/unit-test-pk-netscape-trust.c	(original)
+++ trunk/pk/tests/unit-test-pk-netscape-trust.c	Mon Jan 14 01:22:17 2008
@@ -1,5 +1,5 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* unit-test-pk-cert.c: Test a certificate
+/* unit-test-pk-netscape-trust.c: Test a netscape trust object
 
    Copyright (C) 2007 Stefan Walter
 
@@ -109,7 +109,7 @@
 
 void unit_test_trust_static (CuTest *cu)
 {
-	CHECK_BOOL_ATTRIBUTE (cu, trust_1, CKA_TOKEN, CK_TRUE);
+	CHECK_BOOL_ATTRIBUTE (cu, trust_1, CKA_TOKEN, CK_FALSE);
 	CHECK_BOOL_ATTRIBUTE (cu, trust_1, CKA_TRUST_STEP_UP_APPROVED, CK_FALSE);
 	CHECK_ULONG_ATTRIBUTE (cu, trust_1, CKA_CLASS, CKO_NETSCAPE_TRUST);
 }

Modified: trunk/pkcs11/gkr-pkcs11-calls.h
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-calls.h	(original)
+++ trunk/pkcs11/gkr-pkcs11-calls.h	Mon Jan 14 01:22:17 2008
@@ -108,7 +108,7 @@
 	{ PKCS11_CALL_C_DestroyObject,        "C_DestroyObject",        "u",       ""       },
 	{ PKCS11_CALL_C_GetObjectSize,        "C_GetObjectSize",        "u",       "u"      },
 	{ PKCS11_CALL_C_GetAttributeValue,    "C_GetAttributeValue",    "uaA",     "aAu"    },
-	{ PKCS11_CALL_C_SetAttributeValue,    "C_SetAttributeValue",    "u",       "aA"     },
+	{ PKCS11_CALL_C_SetAttributeValue,    "C_SetAttributeValue",    "uaA",     ""       },
 	{ PKCS11_CALL_C_FindObjectsInit,      "C_FindObjectsInit",      "aA",      ""       },
 	{ PKCS11_CALL_C_FindObjects,          "C_FindObjects",          "u",       "au"     },
 	{ PKCS11_CALL_C_FindObjectsFinal,     "C_FindObjectsFinal",     "",        ""       },

Modified: trunk/pkcs11/gkr-pkcs11-daemon-session.c
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-daemon-session.c	(original)
+++ trunk/pkcs11/gkr-pkcs11-daemon-session.c	Mon Jan 14 01:22:17 2008
@@ -37,6 +37,7 @@
 
 #include "pk/gkr-pk-object.h"
 #include "pk/gkr-pk-object-manager.h"
+#include "pk/gkr-pk-object-storage.h"
 #include "pk/gkr-pk-util.h"
 
 #include <stdlib.h>
@@ -85,16 +86,16 @@
  */
 
 static void
-session_take_object (SessionInfo *sinfo, GkrPkObject *object)
+session_add_object (SessionInfo *sinfo, GkrPkObject *object)
 {
 	g_assert (sinfo);
 	
-	g_return_if_fail (object->handle == 0);
+	g_return_if_fail (object->handle != 0);
 	g_return_if_fail (object->location == 0);
 	g_return_if_fail (object->manager == sinfo->manager);
 
 	/* We assume the ownership */
-	g_assert (object->handle);
+	g_object_ref (object);
 	g_hash_table_insert (sinfo->objects, GUINT_TO_POINTER (object->handle), object);
 }
 
@@ -427,31 +428,19 @@
  * OBJECT OPERATIONS
  */
 
-static CK_RV 
-create_key_object (GkrPkObjectManager *manager, GArray *attrs, GkrPkObject **key)
-{
-	CK_KEY_TYPE type;
-	
-	if (!gkr_pk_attributes_ulong (attrs, CKA_KEY_TYPE, &type))
-		return CKR_TEMPLATE_INCOMPLETE;
-		
-	switch (type) {
-	/* TODO: Support RSA key creation */
-	case CKK_DSA:
-		return gkr_pkcs11_dsa_create_key (manager, attrs, key);
-	default:
-		return CKR_ATTRIBUTE_VALUE_INVALID;
-	};
-}
-
 static CK_RV
 session_C_CreateObject (SessionInfo *sinfo, GkrPkcs11Message *req, 
                         GkrPkcs11Message *resp)
 {
+	GkrPkObjectManager *manager;
+	CK_ATTRIBUTE_PTR attr;
+	CK_OBJECT_CLASS cls;
 	GkrPkObject *object;
 	GArray *attrs = NULL;
-	CK_OBJECT_CLASS cls;
 	CK_BBOOL token;
+	GError *err = NULL;
+	gboolean res;
+	guint i;
 	CK_RV ret;
 	
 	if (sinfo->operation_type)
@@ -463,7 +452,7 @@
 	if (!gkr_pk_attributes_ulong (attrs, CKA_CLASS, &cls)) {
 	    	ret = CKR_TEMPLATE_INCOMPLETE;
 	    	goto done;
-	}
+	} 
 	
 	/* Can only create public objects unless logged in */
 	if (!gkr_keyring_login_is_unlocked () && gkc_pk_class_is_private (cls)) {
@@ -471,43 +460,57 @@
 		goto done;
 	}
 	
-	/* 
-	 * Can only create session objects
-	 * TODO: Support token objects.
-	 * TODO: Take readonly session into account, once we support 
-	 * token objects. CKR_SESSION_READ_ONLY
-	 */
-	if (gkr_pk_attributes_boolean (attrs, CKA_TOKEN, &token) && token) {
-		 ret = CKR_TOKEN_WRITE_PROTECTED;
-		 goto done;
+	/* Find out if its a token object or not */
+	token = CK_FALSE;
+	for (i = 0; i < attrs->len; ++i) {
+		attr = &(g_array_index (attrs, CK_ATTRIBUTE, i));
+		if (attr->type == CKA_TOKEN) {
+			if (attr && attr->pValue && attr->ulValueLen == sizeof (CK_BBOOL))
+				token = *((CK_BBOOL*)attr->pValue);
+				
+			/* Mark that attribute as used */
+			gkr_pk_attribute_consume (attr);
+			break;
+		}
 	}
 	
-	switch (cls) {
-	case CKO_PUBLIC_KEY:
-	case CKO_PRIVATE_KEY:
-		ret = create_key_object (sinfo->manager, attrs, &object);
-		break;
-	default:
-		/* TODO: What's a better error code here? */
-		ret = CKR_FUNCTION_NOT_SUPPORTED;
-		break;
-	};
+	/* A readonly session cannot create token objects */
+	if (token && sinfo->readonly) {
+		ret = CKR_SESSION_READ_ONLY;
+		goto done;
+	}
 
-	if (ret == CKR_OK) {
+	/* Create the object with the right object manager */
+	manager = token ? gkr_pk_object_manager_for_token () : sinfo->manager;
+	ret = gkr_pk_object_create (manager, attrs, &object);
+	                 		
+	if (ret != CKR_OK) 
+		goto done;
 
-		g_return_val_if_fail (object, CKR_GENERAL_ERROR);
-		
-		/* 
-		 * Store it appropriately. 
-		 * TODO: Eventually we will store and write to the token
-		 * storage here, but for now just the session.
-		 */
+	g_return_val_if_fail (object, CKR_GENERAL_ERROR);
 		
-		session_take_object (sinfo, object);
-		gkr_pkcs11_message_write_uint32 (resp, object->handle);
+	/* Token objects get stored in the main object storage */
+	if (token) {
+		g_return_val_if_fail (object->storage != NULL, CKR_GENERAL_ERROR);
+		res = gkr_pk_object_storage_add (gkr_pk_object_storage_get (), object, &err);
+		if (!res) {
+			g_warning ("couldn't write created object to disk: %s", 
+			           err && err->message ? err->message : "");
+			g_clear_error (&err);
+			ret = CKR_GENERAL_ERROR;
+			goto done;
+		}
+			
+	/* Session objects are owned by the session */
+	} else {
+		session_add_object (sinfo, object);
 	}
+
+	gkr_pkcs11_message_write_uint32 (resp, object->handle);
+	ret = CKR_OK;
 	
 done:
+	g_object_unref (object);
 	gkr_pk_attributes_free (attrs);
 	return ret;
 }
@@ -527,11 +530,65 @@
 session_C_DestroyObject (SessionInfo *sinfo, GkrPkcs11Message *req, 
                          GkrPkcs11Message *resp)
 {
-	/* 
-	 * TODO: We need to implement this, initially perhaps only 
-	 * only for session objects.
-	 */
- 	return CKR_FUNCTION_NOT_SUPPORTED;
+	CK_OBJECT_HANDLE obj;
+	GkrPkObjectManager *manager;
+	GkrPkObject *object;
+	CK_RV ret = CKR_OK;
+	gboolean res;
+	GError *err = NULL;
+	CK_BBOOL priv;
+	
+	if (gkr_pkcs11_message_read_uint32 (req, &obj) != CKR_OK)
+		return PROTOCOL_ERROR;
+	
+	/* Find the object in question */
+	if (obj & GKR_PK_OBJECT_IS_PERMANENT)
+		manager = gkr_pk_object_manager_for_token ();
+	else
+		manager = sinfo->manager;
+		
+	object = gkr_pk_object_manager_lookup (manager, obj);
+	if (!object)
+		return CKR_OBJECT_HANDLE_INVALID;
+		
+	/* We can only destroy public objects unless logged in */
+	if (!gkr_keyring_login_is_unlocked ()) {
+		ret = gkr_pk_object_get_bool (object, CKA_PRIVATE, &priv);
+		g_return_val_if_fail (ret == CKR_OK, CKR_GENERAL_ERROR);
+		
+		if (priv)
+			return CKR_USER_NOT_LOGGED_IN;
+	}
+	
+	/* A token object */
+	if (obj & GKR_PK_OBJECT_IS_PERMANENT) {
+
+		/* A readonly session cannot destroy token objects */
+		if (sinfo->readonly)
+			return CKR_SESSION_READ_ONLY;
+			
+		g_return_val_if_fail (object->storage, CKR_GENERAL_ERROR);
+		res = gkr_pk_object_storage_remove (object->storage, object, &err);
+		if (!res) {
+			g_warning ("couldn't remove object from disk: %s", 
+			           err && err->message ? err->message : "");
+			g_clear_error (&err);
+			ret = CKR_GENERAL_ERROR;
+		}
+	
+	/* A session object */
+	} else {
+		/* 
+		 * TODO: This just hides the object, does not destroy. 
+		 * The problem is that we need to locate the actual
+		 * session where this is owned, which we currently 
+		 * don't track.
+		 */
+		gkr_pk_object_manager_unregister (manager, object);
+		ret = CKR_OK;
+	}
+		 
+	return ret;
 }
 
 static CK_RV
@@ -539,7 +596,7 @@
                          GkrPkcs11Message *resp)
 {
 	/* TODO: We need to implement this */
-	return CKR_OBJECT_HANDLE_INVALID;
+	return CKR_FUNCTION_NOT_SUPPORTED;
 }
 
 static CK_RV
@@ -588,8 +645,21 @@
 session_C_SetAttributeValue (SessionInfo *sinfo, GkrPkcs11Message *req, 
                              GkrPkcs11Message *resp)
 {
-	/* TODO: We need to implement this */
-	return CKR_FUNCTION_NOT_SUPPORTED;
+	GkrPkObject *object;
+	GArray* attrs;
+	CK_RV ret;
+	
+	ret = read_object (req, sinfo, &object);
+	if (ret != CKR_OK)
+		return ret;
+
+	if (!(attrs = read_attribute_array (req)))
+		return PROTOCOL_ERROR;
+		
+	ret = gkr_pk_object_set_attributes (object, attrs);
+	gkr_pk_attributes_free (attrs);
+	
+	return ret;
 }
 
 static void 

Modified: trunk/pkcs11/gkr-pkcs11-dsa.c
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-dsa.c	(original)
+++ trunk/pkcs11/gkr-pkcs11-dsa.c	Mon Jan 14 01:22:17 2008
@@ -188,84 +188,3 @@
 
 	return CKR_OK;
 }
-
-CK_RV
-gkr_pkcs11_dsa_create_key (GkrPkObjectManager *mgr, const GArray* attrs, GkrPkObject **key)
-{
-	CK_OBJECT_CLASS cls;
-	gcry_sexp_t skey;
-	gcry_error_t gcry;
-	gcry_mpi_t p = NULL;
-	gcry_mpi_t q = NULL;
-	gcry_mpi_t g = NULL;
-	gcry_mpi_t value = NULL;
-	gcry_mpi_t y = NULL;
-	gboolean priv;
-	CK_RV ret;
-	
-	g_return_val_if_fail (attrs, CKR_GENERAL_ERROR);
-	g_return_val_if_fail (key, CKR_GENERAL_ERROR);
-	
-	/* Figure out if it's public or private */
-	if (!gkr_pk_attributes_ulong (attrs, CKA_CLASS, &cls)) {
-		ret = CKR_TEMPLATE_INCOMPLETE;
-		goto done;
-	}
-	if (cls == CKO_PRIVATE_KEY)
-		priv = TRUE;
-	else if (cls == CKO_PUBLIC_KEY)
-		priv = FALSE;
-	else {
-		ret = CKR_ATTRIBUTE_VALUE_INVALID;
-		goto done;
-	}
-	
-	if (!gkr_pk_attributes_mpi (attrs, CKA_PRIME, &p) ||
-	    !gkr_pk_attributes_mpi (attrs, CKA_SUBPRIME, &q) || 
-	    !gkr_pk_attributes_mpi (attrs, CKA_BASE, &g) ||
-	    !gkr_pk_attributes_mpi (attrs, CKA_VALUE, &value)) {
-	    	ret = CKR_TEMPLATE_INCOMPLETE;
-	    	goto done;
-	} 
-	    	
-	/* Create a private key */
-	if (priv) {
-	    		
-		/* Calculate the public part from the private */
-		y = gcry_mpi_snew (gcry_mpi_get_nbits (value));
-  		gcry_mpi_powm (y, g, value, p);
-  			
-		gcry = gcry_sexp_build (&skey, NULL, "(private-key (dsa (p %m) (q %m) (g %m) (y %m) (x %m)))",
-		                        p, q, g, value);
-	    		
-	/* Create a public key */
-	} else {
-	    		
-		gcry = gcry_sexp_build (&skey, NULL, "(public-key (dsa (p %m) (q %m) (g %m) (y %m)))",
-		                        p, q, g, value);	    		
-    	}
-	
-	/* TODO: We should be mapping better return codes */
-	if (gcry != 0) {
-		g_message ("couldn't create DSA key from passed attributes");
-		ret = CKR_GENERAL_ERROR;
-		goto done;
-	}
-	
-	if (priv) 
-		*key = gkr_pk_privkey_new (mgr, 0, skey);
-	else
-		*key = gkr_pk_pubkey_new (mgr, 0, skey); 
-
-	/* TODO: We should verify remainder of attributes */
-	ret = CKR_OK;
-		
-done:
-	gcry_mpi_release (p);
-	gcry_mpi_release (q);
-	gcry_mpi_release (g);
-	gcry_mpi_release (y);
-	gcry_mpi_release (value);
-	
-	return CKR_OK;
-}

Modified: trunk/pkcs11/gkr-pkcs11-module.c
==============================================================================
--- trunk/pkcs11/gkr-pkcs11-module.c	(original)
+++ trunk/pkcs11/gkr-pkcs11-module.c	Mon Jan 14 01:22:17 2008
@@ -1946,8 +1946,8 @@
 {
 	BEGIN_CALL (session, C_SetAttributeValue);
 		IN_HANDLE (object);
-	PROCESS_CALL;
 		IN_ATTRIBUTE_ARRAY (template, count);
+	PROCESS_CALL;
 	END_CALL;
 }
 



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