Exemple #1
0
/**
 * gck_module_initialize:
 * @path: The file system path to the PKCS#11 module to load.
 * @reserved: Extra arguments for the PKCS#11 module, should usually be NULL.
 * @reserved_options: No options are currently available.
 * @err: A location to store an error resulting from a failed load.
 *
 * Load and initialize a PKCS#11 module represented by a GckModule object.
 *
 * Return value: The loaded PKCS#11 module or NULL if failed.
 **/
GckModule*
gck_module_initialize (const gchar *path, gpointer reserved, guint reserved_options, GError **err)
{
	CK_C_GetFunctionList get_function_list;
	CK_FUNCTION_LIST_PTR funcs;
	GModule *module;
	GckModule *self;
	CK_RV rv;

	g_return_val_if_fail (path != NULL, NULL);
	g_return_val_if_fail (!err || !*err, NULL);

	/* Load the actual module */
	module = g_module_open (path, 0);
	if (!module) {
		g_set_error (err, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
		             "Error loading pkcs11 module: %s", g_module_error ());
		return NULL;
	}

	/* Get the entry point */
	if (!g_module_symbol (module, "C_GetFunctionList", (void**)&get_function_list)) {
		g_set_error (err, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
		             "Invalid pkcs11 module: %s", g_module_error ());
		g_module_close (module);
		return NULL;
	}

	/* Get the function list */
	rv = (get_function_list) (&funcs);
	if (rv != CKR_OK) {
		g_set_error (err, GCK_ERROR, rv, "Couldn't get pkcs11 function list: %s",
		             gck_message_from_rv (rv));
		g_module_close (module);
		return NULL;
	}

	self = g_object_new (GCK_TYPE_MODULE, "functions", funcs, "path", path, NULL);
	self->pv->module = module;

	memset (&self->pv->init_args, 0, sizeof (self->pv->init_args));
	self->pv->init_args.flags = CKF_OS_LOCKING_OK;
	self->pv->init_args.CreateMutex = create_mutex;
	self->pv->init_args.DestroyMutex = destroy_mutex;
	self->pv->init_args.LockMutex = lock_mutex;
	self->pv->init_args.UnlockMutex = unlock_mutex;
	self->pv->init_args.pReserved = reserved;

	/* Now initialize the module */
	rv = (self->pv->funcs->C_Initialize) (&self->pv->init_args);
	if (rv != CKR_OK) {
		g_set_error (err, GCK_ERROR, rv, "Couldn't initialize module: %s",
		             gck_message_from_rv (rv));
		g_object_unref (self);
		return NULL;
	}

	self->pv->initialized = TRUE;
	return self;
}
Exemple #2
0
/**
 * gck_module_get_info:
 * @self: The module to get info for.
 *
 * Get the info about a PKCS#11 module.
 *
 * Return value: The module info. Release this with gck_module_info_free().
 **/
GckModuleInfo*
gck_module_get_info (GckModule *self)
{
	GckModuleInfo *modinfo;
	CK_INFO info;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
	g_return_val_if_fail (self->pv->funcs, NULL);

	memset (&info, 0, sizeof (info));
	rv = (self->pv->funcs->C_GetInfo (&info));
	if (rv != CKR_OK) {
		g_warning ("couldn't get module info: %s", gck_message_from_rv (rv));
		return NULL;
	}

	modinfo = g_new0 (GckModuleInfo, 1);
	modinfo->flags = info.flags;
	modinfo->library_description = gck_string_from_chars (info.libraryDescription,
	                                                       sizeof (info.libraryDescription));
	modinfo->manufacturer_id = gck_string_from_chars (info.manufacturerID,
	                                                   sizeof (info.manufacturerID));
	modinfo->library_version_major = info.libraryVersion.major;
	modinfo->library_version_minor = info.libraryVersion.minor;
	modinfo->pkcs11_version_major = info.cryptokiVersion.major;
	modinfo->pkcs11_version_minor = info.cryptokiVersion.minor;

	return modinfo;
}
Exemple #3
0
static CK_RV
perform_initialize (Initialize *args)
{
	CK_FUNCTION_LIST_PTR funcs;
	GckModule *result;
	CK_RV rv;

	funcs = p11_kit_module_load (args->path, P11_KIT_MODULE_CRITICAL);
	if (funcs == NULL) {
		g_set_error (&args->error, GCK_ERROR, (int)CKR_GCK_MODULE_PROBLEM,
		             _("Error loading PKCS#11 module: %s"), p11_kit_message ());
		return CKR_GCK_MODULE_PROBLEM;
	}

	result = g_object_new (GCK_TYPE_MODULE,
	                       "functions", funcs,
	                       "path", args->path,
	                       NULL);

	/* Now initialize the module */
	rv = p11_kit_module_initialize (funcs);
	if (rv != CKR_OK) {
		p11_kit_module_release (funcs);
		g_set_error (&args->error, GCK_ERROR, rv,
		             _("Couldn’t initialize PKCS#11 module: %s"),
		             gck_message_from_rv (rv));
		g_object_unref (result);
		return rv;
	}

	result->pv->initialized = TRUE;
	args->result = result;
	return CKR_OK;
}
Exemple #4
0
/**
 * gck_slot_has_flags:
 * @self: The GckSlot object.
 * @flags: The flags to check.
 *
 * Check if the PKCS11 slot has the given flags.
 *
 * Returns: Whether one or more flags exist.
 */
gboolean
gck_slot_has_flags (GckSlot *self, gulong flags)
{
	CK_FUNCTION_LIST_PTR funcs;
	GckModule *module = NULL;
	CK_TOKEN_INFO info;
	CK_SLOT_ID handle;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_SLOT (self), FALSE);

	g_object_get (self, "module", &module, "handle", &handle, NULL);
	g_return_val_if_fail (GCK_IS_MODULE (module), FALSE);

	funcs = gck_module_get_functions (module);
	g_return_val_if_fail (funcs, FALSE);

	memset (&info, 0, sizeof (info));
	rv = (funcs->C_GetTokenInfo) (handle, &info);

	g_object_unref (module);

	if (rv != CKR_OK) {
		g_warning ("couldn't get slot info: %s", gck_message_from_rv (rv));
		return FALSE;
	}

	return (info.flags & flags) != 0;
}
Exemple #5
0
/**
 * gck_slot_get_mechanisms:
 * @self: The slot to get mechanisms for.
 *
 * Get the available mechanisms for this slot.
 *
 * Return value: A list of the mechanisms for this slot. Use
 * gck_mechanisms_free() when done with this.
 **/
GckMechanisms*
gck_slot_get_mechanisms (GckSlot *self)
{
	CK_SLOT_ID handle = (CK_SLOT_ID)-1;
	CK_FUNCTION_LIST_PTR funcs;
	GckModule *module = NULL;
	CK_MECHANISM_TYPE_PTR mech_list = NULL;
	CK_ULONG count, i;
	GckMechanisms *result;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_SLOT (self), NULL);

	g_object_get (self, "module", &module, "handle", &handle, NULL);
	g_return_val_if_fail (GCK_IS_MODULE (module), NULL);

	funcs = gck_module_get_functions (module);
	g_return_val_if_fail (funcs, NULL);

	rv = (funcs->C_GetMechanismList) (handle, NULL, &count);
	if (rv != CKR_OK) {
		g_warning ("couldn't get mechanism count: %s", gck_message_from_rv (rv));
		count = 0;
	} else {
		mech_list = g_new (CK_MECHANISM_TYPE, count);
		rv = (funcs->C_GetMechanismList) (handle, mech_list, &count);
		if (rv != CKR_OK) {
			g_warning ("couldn't get mechanism list: %s", gck_message_from_rv (rv));
			g_free (mech_list);
			count = 0;
		}
	}

	g_object_unref (module);

	if (!count)
		return NULL;

	result = g_array_new (FALSE, TRUE, sizeof (CK_MECHANISM_TYPE));
	for (i = 0; i < count; ++i)
		g_array_append_val (result, mech_list[i]);

	g_free (mech_list);
	return result;

}
Exemple #6
0
static GckObject *
lookup_public_key (GckObject *object,
                   GCancellable *cancellable,
                   GError **lerror)
{
	GckBuilder builder = GCK_BUILDER_INIT;
	gulong attr_types[] = { CKA_ID };
	GckAttributes *attrs;
	GError *error = NULL;
	GckSession *session;
	GckObject *result;
	const GckAttribute *id;
	GList *objects;

	attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
	                                 cancellable, &error);
	if (error != NULL) {
		_gcr_debug ("couldn't load private key id: %s", error->message);
		g_propagate_error (lerror, error);
		return NULL;
	}

	id = gck_attributes_find (attrs, CKA_ID);
	if (id == NULL || gck_attribute_is_invalid (id)) {
		gck_attributes_unref (attrs);
		_gcr_debug ("couldn't load private key id");
		g_set_error_literal (lerror, GCK_ERROR, CKR_ATTRIBUTE_TYPE_INVALID,
		                     gck_message_from_rv (CKR_ATTRIBUTE_TYPE_INVALID));
		return NULL;
	}

	gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
	gck_builder_add_attribute (&builder, id);
	gck_attributes_unref (attrs);

	session = gck_object_get_session (object);
	objects = gck_session_find_objects (session, gck_builder_end (&builder), cancellable, &error);
	g_object_unref (session);

	if (error != NULL) {
		_gcr_debug ("couldn't lookup public key: %s", error->message);
		g_propagate_error (lerror, error);
		return NULL;
	}

	if (!objects)
		return NULL;

	result = g_object_ref (objects->data);
	gck_list_unref_free (objects);

	return result;
}
Exemple #7
0
/**
 * gck_module_get_slots:
 * @self: The module for which to get the slots.
 * @token_present: Whether to limit only to slots with a token present.
 *
 * Get the GckSlot objects for a given module.
 *
 * Return value: The possibly empty list of slots. Release this with gck_list_unref_free().
 */
GList*
gck_module_get_slots (GckModule *self, gboolean token_present)
{
	CK_SLOT_ID_PTR slot_list;
	CK_ULONG count, i;
	GList *result;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
	g_return_val_if_fail (self->pv->funcs, NULL);

	rv = (self->pv->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, NULL, &count);
	if (rv != CKR_OK) {
		g_warning ("couldn't get slot count: %s", gck_message_from_rv (rv));
		return NULL;
	}

	if (!count)
		return NULL;

	slot_list = g_new (CK_SLOT_ID, count);
	rv = (self->pv->funcs->C_GetSlotList) (token_present ? CK_TRUE : CK_FALSE, slot_list, &count);
	if (rv != CKR_OK) {
		g_warning ("couldn't get slot list: %s", gck_message_from_rv (rv));
		g_free (slot_list);
		return NULL;
	}

	result = NULL;
	for (i = 0; i < count; ++i) {
		result = g_list_prepend (result, g_object_new (GCK_TYPE_SLOT,
		                                               "handle", slot_list[i],
		                                               "module", self, NULL));
	}

	g_free (slot_list);
	return g_list_reverse (result);
}
Exemple #8
0
gboolean
_gck_call_basic_finish (GAsyncResult *result, GError **err)
{
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_CALL (result), FALSE);

	rv = GCK_CALL (result)->rv;
	if (rv == CKR_OK)
		return TRUE;

	g_set_error (err, GCK_ERROR, rv, "%s", gck_message_from_rv (rv));
	return FALSE;
}
Exemple #9
0
/**
 * gck_module_get_info:
 * @self: The module to get info for.
 *
 * Get the info about a PKCS\#11 module.
 *
 * Returns: (transfer full): the module info; release this with gck_module_info_free()
 **/
GckModuleInfo*
gck_module_get_info (GckModule *self)
{
	CK_INFO info;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_MODULE (self), NULL);
	g_return_val_if_fail (self->pv->funcs, NULL);

	memset (&info, 0, sizeof (info));
	rv = (self->pv->funcs->C_GetInfo (&info));
	if (rv != CKR_OK) {
		g_warning ("couldn't get module info: %s", gck_message_from_rv (rv));
		return NULL;
	}

	return _gck_module_info_from_pkcs11 (&info);
}
Exemple #10
0
/**
 * gck_slot_get_info:
 * @self: The slot to get info for.
 *
 * Get the information for this slot.
 *
 * Return value: The slot information. When done, use gck_slot_info_free()
 * to release it.
 **/
GckSlotInfo*
gck_slot_get_info (GckSlot *self)
{
	CK_SLOT_ID handle = (CK_SLOT_ID)-1;
	GckModule *module = NULL;
	CK_FUNCTION_LIST_PTR funcs;
	GckSlotInfo *slotinfo;
	CK_SLOT_INFO info;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_SLOT (self), NULL);

	g_object_get (self, "module", &module, "handle", &handle, NULL);
	g_return_val_if_fail (GCK_IS_MODULE (module), NULL);

	funcs = gck_module_get_functions (module);
	g_return_val_if_fail (funcs, NULL);

	memset (&info, 0, sizeof (info));
	rv = (funcs->C_GetSlotInfo) (handle, &info);

	g_object_unref (module);

	if (rv != CKR_OK) {
		g_warning ("couldn't get slot info: %s", gck_message_from_rv (rv));
		return NULL;
	}

	slotinfo = g_new0 (GckSlotInfo, 1);
	slotinfo->slot_description = gck_string_from_chars (info.slotDescription,
	                                                     sizeof (info.slotDescription));
	slotinfo->manufacturer_id = gck_string_from_chars (info.manufacturerID,
	                                                    sizeof (info.manufacturerID));
	slotinfo->flags = info.flags;
	slotinfo->hardware_version_major = info.hardwareVersion.major;
	slotinfo->hardware_version_minor = info.hardwareVersion.minor;
	slotinfo->firmware_version_major = info.firmwareVersion.major;
	slotinfo->firmware_version_minor = info.firmwareVersion.minor;

	return slotinfo;
}
Exemple #11
0
static void
gck_module_dispose (GObject *obj)
{
	GckModule *self = GCK_MODULE (obj);
	gboolean finalize = FALSE;
	CK_RV rv;

	if (self->pv->initialized && self->pv->funcs) {
		if (g_atomic_int_compare_and_exchange (&self->pv->finalized, 0, 1))
			finalize = TRUE;
	}

	/* Must be careful when accessing funcs */
	if (finalize) {
		rv = (self->pv->funcs->C_Finalize) (NULL);
		if (rv != CKR_OK) {
			g_warning ("C_Finalize on module '%s' failed: %s",
			           self->pv->path, gck_message_from_rv (rv));
		}
	}

	G_OBJECT_CLASS (gck_module_parent_class)->dispose (obj);
}
Exemple #12
0
gboolean
_gck_call_sync (gpointer object, gpointer perform, gpointer complete,
                 gpointer data, GCancellable *cancellable, GError **err)
{
	GckArguments *args = (GckArguments*)data;
	GckModule *module = NULL;
	CK_RV rv;

	g_assert (!object || G_IS_OBJECT (object));
	g_assert (perform);
	g_assert (args);

	if (object) {
		g_object_get (object, "module", &module, "handle", &args->handle, NULL);
		g_assert (GCK_IS_MODULE (module));

		/* We now hold a reference to module until below */
		args->pkcs11 = gck_module_get_functions (module);
		g_assert (args->pkcs11);
	}

	do {
		rv = perform_call (perform, cancellable, args);
		if (rv == CKR_FUNCTION_CANCELED)
			break;

	} while (!complete_call (complete, args, rv));

	if (module)
		g_object_unref (module);

	if (rv == CKR_OK)
		return TRUE;

	g_set_error (err, GCK_ERROR, rv, "%s", gck_message_from_rv (rv));
	return FALSE;
}
Exemple #13
0
/**
 * gck_slot_get_mechanism_info:
 * @self: The slot to get mechanism info from.
 * @mech_type: The mechanisms type to get info for.
 *
 * Get information for the specified mechanism.
 *
 * Return value: The mechanism information, or NULL if failed. Use
 * gck_mechanism_info_free() when done with it.
 **/
GckMechanismInfo*
gck_slot_get_mechanism_info (GckSlot *self, gulong mech_type)
{
	CK_SLOT_ID handle = (CK_SLOT_ID)-1;
	CK_FUNCTION_LIST_PTR funcs;
	GckMechanismInfo *mechinfo;
	GckModule *module = NULL;
	CK_MECHANISM_INFO info;
	struct tm;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_SLOT (self), NULL);

	g_object_get (self, "module", &module, "handle", &handle, NULL);
	g_return_val_if_fail (GCK_IS_MODULE (module), NULL);

	funcs = gck_module_get_functions (module);
	g_return_val_if_fail (funcs, NULL);

	memset (&info, 0, sizeof (info));
	rv = (funcs->C_GetMechanismInfo) (handle, mech_type, &info);

	g_object_unref (module);

	if (rv != CKR_OK) {
		g_warning ("couldn't get mechanism info: %s", gck_message_from_rv (rv));
		return NULL;
	}

	mechinfo = g_new0 (GckMechanismInfo, 1);
	mechinfo->flags = info.flags;
	mechinfo->max_key_size = info.ulMaxKeySize;
	mechinfo->min_key_size = info.ulMinKeySize;

	return mechinfo;
}
Exemple #14
0
/**
 * gck_slot_get_token_info:
 * @self: The slot to get info for.
 *
 * Get the token information for this slot.
 *
 * Return value: The token information. When done, use gck_token_info_free()
 * to release it.
 **/
GckTokenInfo*
gck_slot_get_token_info (GckSlot *self)
{
	CK_SLOT_ID handle = (CK_SLOT_ID)-1;
	CK_FUNCTION_LIST_PTR funcs;
	GckModule *module = NULL;
	GckTokenInfo *tokeninfo;
	CK_TOKEN_INFO info;
	gchar *string;
	struct tm tm;
	CK_RV rv;

	g_return_val_if_fail (GCK_IS_SLOT (self), NULL);

	g_object_get (self, "module", &module, "handle", &handle, NULL);
	g_return_val_if_fail (GCK_IS_MODULE (module), NULL);

	funcs = gck_module_get_functions (module);
	g_return_val_if_fail (funcs, NULL);

	memset (&info, 0, sizeof (info));
	rv = (funcs->C_GetTokenInfo) (handle, &info);

	g_object_unref (module);

	if (rv != CKR_OK) {
		g_warning ("couldn't get slot info: %s", gck_message_from_rv (rv));
		return NULL;
	}

	tokeninfo = g_new0 (GckTokenInfo, 1);
	tokeninfo->label = gck_string_from_chars (info.label, sizeof (info.label));
	tokeninfo->model = gck_string_from_chars (info.model, sizeof (info.model));
	tokeninfo->manufacturer_id = gck_string_from_chars (info.manufacturerID,
	                                                     sizeof (info.manufacturerID));
	tokeninfo->serial_number = gck_string_from_chars (info.serialNumber,
	                                                   sizeof (info.serialNumber));
	tokeninfo->flags = info.flags;
	tokeninfo->max_session_count = info.ulMaxSessionCount;
	tokeninfo->session_count = info.ulSessionCount;
	tokeninfo->max_rw_session_count = info.ulMaxRwSessionCount;
	tokeninfo->rw_session_count = info.ulRwSessionCount;
	tokeninfo->max_pin_len = info.ulMaxPinLen;
	tokeninfo->min_pin_len = info.ulMinPinLen;
	tokeninfo->total_public_memory = info.ulTotalPublicMemory;
	tokeninfo->total_private_memory = info.ulTotalPrivateMemory;
	tokeninfo->free_private_memory = info.ulFreePrivateMemory;
	tokeninfo->free_public_memory = info.ulFreePublicMemory;
	tokeninfo->hardware_version_major = info.hardwareVersion.major;
	tokeninfo->hardware_version_minor = info.hardwareVersion.minor;
	tokeninfo->firmware_version_major = info.firmwareVersion.major;
	tokeninfo->firmware_version_minor = info.firmwareVersion.minor;

	/* Parse the time into seconds since epoch */
	if (info.flags & CKF_CLOCK_ON_TOKEN) {
		string = g_strndup ((gchar*)info.utcTime, MIN (14, sizeof (info.utcTime)));
		if (!strptime (string, "%Y%m%d%H%M%S", &tm))
			tokeninfo->utc_time = -1;
		else
			tokeninfo->utc_time = timegm (&tm);
		g_free (string);
	} else {
		tokeninfo->utc_time = -1;
	}

	return tokeninfo;
}