CK_RV
gkm_module_C_GetSlotInfo (GkmModule *self, CK_SLOT_ID id, CK_SLOT_INFO_PTR info)
{
	const CK_SLOT_INFO *original;
	GkmModuleClass *klass;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	if (id != GKM_SLOT_ID)
		return CKR_SLOT_ID_INVALID;
	if (info == NULL)
		return CKR_ARGUMENTS_BAD;

	/* Any slot ID is valid for partitioned module */

	klass = GKM_MODULE_GET_CLASS (self);
	g_return_val_if_fail (klass, CKR_GENERAL_ERROR);
	g_return_val_if_fail (klass->get_slot_info, CKR_GENERAL_ERROR);

	original = (klass->get_slot_info) (self);
	g_return_val_if_fail (original, CKR_GENERAL_ERROR);

	memcpy (info, original, sizeof (CK_SLOT_INFO));

	/* Extend all the strings appropriately */
	extend_space_string (info->manufacturerID, sizeof (info->manufacturerID));
	extend_space_string (info->slotDescription, sizeof (info->slotDescription));

	return CKR_OK;
}
CK_RV
gkm_module_C_CloseAllSessions (GkmModule *self, CK_SLOT_ID id)
{
	Apartment *apt;
	CK_SESSION_HANDLE handle;
	GList *l;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	if (APARTMENT_SLOT (id) != GKM_SLOT_ID)
		return CKR_SLOT_ID_INVALID;

	apt = lookup_apartment (self, id);
	if (apt == NULL)
		return CKR_OK;

	/* Unregister all its sessions */
	for (l = apt->sessions; l; l = g_list_next (l)) {
		handle = gkm_session_get_handle (l->data);
		if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle))
			g_assert_not_reached ();
	}

	unregister_apartment (self, apt);
	return CKR_OK;
}
CK_RV
gkm_module_login_so (GkmModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_GENERAL_ERROR);
	g_assert (GKM_MODULE_GET_CLASS (self)->login_so);
	return GKM_MODULE_GET_CLASS (self)->login_so (self, slot_id, pin, n_pin);
}
CK_RV
gkm_module_C_GetMechanismInfo (GkmModule *self, CK_SLOT_ID id,
                               CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info)
{
	const guint n_mechanisms = G_N_ELEMENTS (mechanism_list);
	guint index;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	if (id != GKM_SLOT_ID)
		return CKR_SLOT_ID_INVALID;
	if (info == NULL)
		return CKR_ARGUMENTS_BAD;

	for (index = 0; index < n_mechanisms; ++index) {
		if (mechanism_list[index].mechanism == type)
			break;
	}

	if (index == n_mechanisms)
		return CKR_MECHANISM_INVALID;

	memcpy (info, &mechanism_list[index].info, sizeof (CK_MECHANISM_INFO));
	return CKR_OK;
}
CK_RV
gkm_module_C_CloseSession (GkmModule *self, CK_SESSION_HANDLE handle)
{
	GkmSession *session;
	CK_ULONG apt_id;
	Apartment *apt;
	GList *link;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	session = gkm_module_lookup_session (self, handle);
	if (session == NULL)
		return CKR_SESSION_HANDLE_INVALID;

	/* Calculate the virtual slot */
	apt_id = gkm_session_get_apartment (session);
	apt = lookup_apartment (self, apt_id);
	g_return_val_if_fail (apt, CKR_GENERAL_ERROR);

	link = g_list_find (apt->sessions, session);
	g_return_val_if_fail (link, CKR_GENERAL_ERROR);
	apt->sessions = g_list_delete_link (apt->sessions, link);
	g_object_unref (session);
	if (!apt->sessions)
		unregister_apartment (self, apt);

	if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle))
		g_assert_not_reached ();

	return CKR_OK;
}
CK_RV
gkm_module_C_GetMechanismList (GkmModule *self, CK_SLOT_ID id,
                               CK_MECHANISM_TYPE_PTR mech_list, CK_ULONG_PTR count)
{
	const guint n_mechanisms = G_N_ELEMENTS (mechanism_list);
	guint i;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	if (id != GKM_SLOT_ID)
		return CKR_SLOT_ID_INVALID;
	if (count == NULL)
		return CKR_ARGUMENTS_BAD;

	/* Just want to get the count */
	if (mech_list == NULL) {
		*count = n_mechanisms;
		return CKR_OK;
	}

	/* Buffer too small? */
	if (*count < n_mechanisms) {
		*count = n_mechanisms;
		return CKR_BUFFER_TOO_SMALL;
	}

	*count = n_mechanisms;
	for (i = 0; i < n_mechanisms; ++i)
		mech_list[i] = mechanism_list[i].mechanism;

	return CKR_OK;
}
GkmModule*
gkm_object_get_module (GkmObject *self)
{
	g_return_val_if_fail (GKM_IS_OBJECT (self), NULL);
	g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL);
	return self->pv->module;
}
static void
gkm_object_get_property (GObject *obj, guint prop_id, GValue *value,
                           GParamSpec *pspec)
{
	GkmObject *self = GKM_OBJECT (obj);

	switch (prop_id) {
	case PROP_HANDLE:
		g_value_set_ulong (value, gkm_object_get_handle (self));
		break;
	case PROP_MODULE:
		g_return_if_fail (GKM_IS_MODULE (self->pv->module));
		g_value_set_object (value, gkm_object_get_module (self));
		break;
	case PROP_MANAGER:
		g_value_set_object (value, gkm_object_get_manager (self));
		break;
	case PROP_STORE:
		g_value_set_object (value, self->pv->store);
		break;
	case PROP_UNIQUE:
		g_value_set_string (value, gkm_object_get_unique (self));
		break;
	case PROP_TRANSIENT:
		g_value_set_boolean (value, gkm_object_is_transient (self));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
		break;
	}
}
CK_RV
gkm_module_C_Logout (GkmModule *self, CK_SESSION_HANDLE handle)
{
	CK_ULONG apt_id;
	Apartment *apt;
	GkmSession *session;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	session = gkm_module_lookup_session (self, handle);
	if (session == NULL)
		return CKR_SESSION_HANDLE_INVALID;

	apt_id = gkm_session_get_apartment (session);
	apt = lookup_apartment (self, apt_id);
	g_return_val_if_fail (apt, CKR_GENERAL_ERROR);

	if (apt->logged_in == CKU_NONE)
		return CKR_USER_NOT_LOGGED_IN;

	else if (apt->logged_in == CKU_USER)
		return gkm_module_logout_user (self, apt_id);

	else if (apt->logged_in == CKU_SO)
		return gkm_module_logout_so (self, apt_id);

	else
		g_return_val_if_reached (CKR_GENERAL_ERROR);
}
CK_RV
gkm_module_C_InitPIN (GkmModule* self, CK_SESSION_HANDLE handle,
                      CK_UTF8CHAR_PTR pin, CK_ULONG n_pin)
{
	GkmSession *session;
	Apartment *apt;
	CK_ULONG apt_id;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	session = gkm_module_lookup_session (self, handle);
	if (session == NULL)
		return CKR_SESSION_HANDLE_INVALID;

	/* Calculate the virtual slot */
	apt_id = gkm_session_get_apartment (session);
	apt = lookup_apartment (self, apt_id);
	g_return_val_if_fail (apt, CKR_GENERAL_ERROR);

	if (apt->logged_in != CKU_SO)
		return CKR_USER_NOT_LOGGED_IN;

	/* Our InitPIN assumes an uninitialized PIN */
	return gkm_module_login_change (self, apt_id, NULL, 0, pin, n_pin);
}
CK_RV
gkm_module_logout_so (GkmModule *self, CK_SLOT_ID slot_id)
{
	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_GENERAL_ERROR);
	g_assert (GKM_MODULE_GET_CLASS (self)->logout_so);
	return GKM_MODULE_GET_CLASS (self)->logout_so (self, slot_id);
}
GkmManager*
gkm_module_get_manager (GkmModule *self)
{
	g_return_val_if_fail (GKM_IS_MODULE (self), NULL);
	g_return_val_if_fail (GKM_IS_MANAGER (self->pv->token_manager), NULL);
	return self->pv->token_manager;
}
CK_RV
gkm_module_refresh_token (GkmModule *self)
{
	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_GENERAL_ERROR);
	g_assert (GKM_MODULE_GET_CLASS (self)->refresh_token);
	return GKM_MODULE_GET_CLASS (self)->refresh_token (self);
}
GkmFactory*
gkm_module_find_factory (GkmModule *self, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
{
	GkmFactory *factory;
	gboolean matched;
	gulong j;
	gsize i;

	g_return_val_if_fail (GKM_IS_MODULE (self), NULL);
	g_return_val_if_fail (attrs || !n_attrs, NULL);

	if (!self->pv->factories_sorted) {
		g_array_sort (self->pv->factories, sort_factory_by_n_attrs);
		self->pv->factories_sorted = TRUE;
	}

	for (i = 0; i < self->pv->factories->len; ++i) {
		factory = &(g_array_index (self->pv->factories, GkmFactory, i));

		matched = TRUE;
		for (j = 0; j < factory->n_attrs; ++j) {
			if (!gkm_attributes_contains (attrs, n_attrs, &factory->attrs[j])) {
				matched = FALSE;
				break;
			}
		}

		if (matched)
			return factory;
	}

	return NULL;
}
CK_RV
gkm_module_C_GetSlotList (GkmModule *self, CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count)
{
	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	if (!count)
		return CKR_ARGUMENTS_BAD;

	/* Just want to get the count */
	if (slot_list == NULL) {
		*count = 1;
		return CKR_OK;
	}

	/* Buffer too small? */
	if (*count == 0) {
		*count = 1;
		return CKR_BUFFER_TOO_SMALL;
	}

	g_return_val_if_fail (slot_list, CKR_ARGUMENTS_BAD);

	/* Answer C_GetSlotList with 0 for app */
	slot_list[0] = GKM_SLOT_ID;
	*count = 1;
	return CKR_OK;
}
static void
unregister_apartment (GkmModule *self, Apartment *apt)
{
	g_assert (apt);
	g_assert (GKM_IS_MODULE (self));

	if (!g_hash_table_remove (self->pv->apartments_by_id, &(apt->apt_id)))
		g_assert_not_reached ();
}
static void
register_apartment (GkmModule *self, Apartment *apt)
{
	g_assert (apt);
	g_assert (GKM_IS_MODULE (self));
	g_assert (!g_hash_table_lookup (self->pv->apartments_by_id, &(apt->apt_id)));

	g_hash_table_insert (self->pv->apartments_by_id,
	                     gkm_util_ulong_alloc (apt->apt_id), apt);
}
static GObject*
gkm_object_constructor (GType type, guint n_props, GObjectConstructParam *props)
{
	GkmObject *self = GKM_OBJECT (G_OBJECT_CLASS (gkm_object_parent_class)->constructor(type, n_props, props));

	g_return_val_if_fail (self, NULL);
	g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL);

	return G_OBJECT (self);
}
void
gkm_module_store_token_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object)
{
	g_return_if_fail (GKM_IS_MODULE (self));
	g_return_if_fail (GKM_IS_OBJECT (object));
	g_assert (GKM_MODULE_GET_CLASS (self)->store_token_object);

	if (!gkm_object_is_transient (object))
		GKM_MODULE_GET_CLASS (self)->store_token_object (self, transaction, object);
}
CK_ULONG
gkm_module_next_handle (GkmModule *self)
{
	g_return_val_if_fail (GKM_IS_MODULE (self), 0);
	if (self->pv->handle_counter == CK_MATE_MAX_HANDLE) {
		g_warning ("handle counter wrapped");
		self->pv->handle_counter = 0;
	}
	return (self->pv->handle_counter)++;
}
Exemplo n.º 21
0
GkmXdgTrust*
gkm_xdg_trust_create_for_assertion (GkmModule *module, GkmManager *manager,
                                    GkmTransaction *transaction,
                                    CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
{

	CK_ATTRIBUTE_PTR serial, issuer, cert;
	GkmXdgTrust *trust;

	g_return_val_if_fail (GKM_IS_MODULE (module), NULL);
	g_return_val_if_fail (GKM_IS_MANAGER (manager), NULL);
	g_return_val_if_fail (attrs || !n_attrs, NULL);

	serial = gkm_attributes_find (attrs, n_attrs, CKA_SERIAL_NUMBER);
	issuer = gkm_attributes_find (attrs, n_attrs, CKA_ISSUER);
	cert = gkm_attributes_find (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE);

	/* A trust object with just serial + issuer */
	if (serial != NULL && issuer != NULL) {
		if (cert != NULL) {
			gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
			return NULL;
		}
		if (!validate_der (issuer, "Name") || !validate_integer (serial)) {
			gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
			return NULL;
		}

		trust = create_trust_for_reference (module, manager, serial, issuer);

	/* A trust object with a full certificate */
	} else if (cert != NULL) {
		if (serial != NULL || issuer != NULL) {
			gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT);
			return NULL;
		}
		if (!validate_der (cert, "Certificate")) {
			gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
			return NULL;
		}

		trust = create_trust_for_complete (module, manager, cert);

	/* Not sure what this is */
	} else {
		gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
		return NULL;
	}

	gkm_attributes_consume (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE, CKA_ISSUER,
	                        CKA_SERIAL_NUMBER, G_MAXULONG);

	return trust;
}
void
gkm_module_register_factory (GkmModule *self, GkmFactory *factory)
{
	g_return_if_fail (GKM_IS_MODULE (self));
	g_return_if_fail (factory);
	g_return_if_fail (factory->attrs || !factory->n_attrs);
	g_return_if_fail (factory->func);

	g_array_append_val (self->pv->factories, *factory);
	self->pv->factories_sorted = FALSE;
}
static void
gkm_object_set_property (GObject *obj, guint prop_id, const GValue *value,
                           GParamSpec *pspec)
{
	GkmObject *self = GKM_OBJECT (obj);
	GkmStore *store;

	switch (prop_id) {
	case PROP_HANDLE:
		gkm_object_set_handle (self, g_value_get_ulong (value));
		break;
	case PROP_MODULE:
		g_return_if_fail (!self->pv->module);
		self->pv->module = g_value_get_object (value);
		g_return_if_fail (GKM_IS_MODULE (self->pv->module));
		g_object_weak_ref (G_OBJECT (self->pv->module), module_went_away, self);
		break;
	case PROP_MANAGER:
		g_return_if_fail (!self->pv->manager);
		self->pv->manager = g_value_get_object (value);
		if (self->pv->manager) {
			g_object_add_weak_pointer (G_OBJECT (self->pv->manager),
			                           (gpointer*)&(self->pv->manager));
		}
		break;
	case PROP_STORE:
		store = g_value_get_object (value);
		if (self->pv->store) {
			g_return_if_fail (!store);
			g_object_remove_weak_pointer (G_OBJECT (self->pv->store),
			                              (gpointer*)&(self->pv->store));
		}
		self->pv->store = store;
		if (self->pv->store)
			g_object_add_weak_pointer (G_OBJECT (self->pv->store),
			                           (gpointer*)&(self->pv->store));

		g_object_notify (G_OBJECT (self), "store");
		break;
	case PROP_UNIQUE:
		g_return_if_fail (!self->pv->unique);
		self->pv->unique = g_value_dup_string (value);
		break;
	case PROP_TRANSIENT:
		g_return_if_fail (!self->pv->transient);
		if (g_value_get_boolean (value))
			mark_object_transient (self);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
		break;
	}
}
static void
mark_login_apartment (GkmModule *self, Apartment *apt, CK_USER_TYPE user)
{
	GList *l;

	g_assert (apt);
	g_assert (GKM_IS_MODULE (self));

	/* Mark all sessions in the partition as logged in */
	for (l = apt->sessions; l; l = g_list_next (l))
		gkm_session_set_logged_in (l->data, user);
	apt->logged_in = user;
}
gboolean
gkm_module_get_write_protected (GkmModule *self)
{
	const CK_TOKEN_INFO* info;

	g_return_val_if_fail (GKM_IS_MODULE (self), TRUE);
	g_return_val_if_fail (GKM_MODULE_GET_CLASS (self)->get_token_info, TRUE);

	info = (GKM_MODULE_GET_CLASS (self)->get_token_info) (self);
	g_return_val_if_fail (info, TRUE);

	return info->flags & CKF_WRITE_PROTECTED;
}
CK_RV
gkm_module_C_Login (GkmModule *self, CK_SESSION_HANDLE handle, CK_USER_TYPE user_type,
                    CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
{
	CK_ULONG apt_id;
	GkmSession *session;
	Apartment *apt;
	GList *l;

	g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED);

	session = gkm_module_lookup_session (self, handle);
	if (session == NULL)
		return CKR_SESSION_HANDLE_INVALID;

	/* Pass off context specifc logins to appropriate place */
	if (user_type == CKU_CONTEXT_SPECIFIC)
		return gkm_session_login_context_specific (session, pin, pin_len);

	/* Some random crap... */
	if (user_type != CKU_USER && user_type != CKU_SO)
		return CKR_USER_TYPE_INVALID;

	/* Calculate the virtual slot */
	apt_id = gkm_session_get_apartment (session);
	apt = lookup_apartment (self, apt_id);
	g_return_val_if_fail (apt, CKR_GENERAL_ERROR);

	if (apt->logged_in == user_type)
		return CKR_USER_ALREADY_LOGGED_IN;
	if (apt->logged_in != CKU_NONE)
		return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;

	if (user_type == CKU_SO) {

		/* Can't login as SO if read-only sessions exist */
		for (l = apt->sessions; l; l = g_list_next (l)) {
			if (gkm_session_get_read_only (l->data))
				return CKR_SESSION_READ_ONLY_EXISTS;
		}

		return gkm_module_login_so (self, apt_id, pin, pin_len);

	} else if (user_type == CKU_USER) {
		return gkm_module_login_user (self, apt_id, pin, pin_len);

	} else {
		return CKR_USER_TYPE_INVALID;
	}
}
void
gkm_module_add_token_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object)
{
	g_return_if_fail (GKM_IS_MODULE (self));
	g_return_if_fail (GKM_IS_OBJECT (object));
	g_assert (GKM_MODULE_GET_CLASS (self)->add_token_object);

	if (gkm_object_is_transient (object)) {
		if (g_hash_table_lookup (self->pv->transient_objects, object) == NULL)
			add_transient_object (self, transaction, object);
	} else {
		GKM_MODULE_GET_CLASS (self)->add_token_object (self, transaction, object);
	}
}
GkmSession*
gkm_module_lookup_session (GkmModule *self, CK_SESSION_HANDLE handle)
{
	GkmSession *session;

	g_return_val_if_fail (GKM_IS_MODULE (self), NULL);

	session = g_hash_table_lookup (self->pv->sessions_by_handle, &handle);
	if (!session)
		return NULL;

	g_return_val_if_fail (GKM_IS_SESSION (session), NULL);
	return session;
}
Exemplo n.º 29
0
GkmMate2Storage*
gkm_mate2_storage_new (GkmModule *module, const gchar *directory)
{
    GkmManager *manager;

    g_return_val_if_fail (GKM_IS_MODULE (module), NULL);
    g_return_val_if_fail (directory, NULL);

    manager = gkm_module_get_manager (module);
    g_return_val_if_fail (GKM_IS_MANAGER (manager), NULL);

    return g_object_new (GKM_TYPE_MATE2_STORAGE,
                         "module", module,
                         "manager", manager,
                         "directory", directory,
                         NULL);
}
static void
add_transient_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object)
{
	g_assert (GKM_IS_MODULE (self));
	g_assert (GKM_IS_OBJECT (object));

	/* Must not already be associated with a session or manager */
	g_return_if_fail (gkm_object_get_manager (object) == self->pv->token_manager);
	g_return_if_fail (g_hash_table_lookup (self->pv->transient_objects, object) == NULL);

	g_hash_table_insert (self->pv->transient_objects, object, g_object_ref (object));
	g_object_set (object, "store", self->pv->transient_store, NULL);
	gkm_object_expose (object, TRUE);

	if (transaction) {
		gkm_transaction_add (transaction, self,
		                     (GkmTransactionFunc)complete_transient_add,
		                     g_object_ref (object));
	}
}