Posted by: Airtower | 2010-08-23

GnuTLS and GLib, Part 1: Threads

[Edit (2011-12-25)] It looks like the way to select the the mutex functions changed slightly since I published this post. Please consult the current documentation to see the difference! [/Edit]

When a network application needs privacy and possibly authentication, using SSL or TLS is often the solution. One of the libraries that are commonly used to support this is GnuTLS. However, I had some problems getting GLib and GnuTLS to play together nicely. This is a description of the problems I found and how I solved them (see part 2 here).

This is not a complete tutorial, I strongly recommend reading the GnuTLS manual. If you’re looking for something simple to get started, I recommend the anonymous authentication server and client examples. Just remember that anonymous authentication means that while the connection is encrypted you have absolutely no proof of who you’re communicating with. If you need stronger security, GnuTLS supports many different authentication methods.

Threads

Programs that use networking are often threaded, especially on the server side, where threads are needed to respond to multiple requests at the same time. This leads to the question how to use GnuTLS in a thread-safe manner.

The official documentation on this matter is rather short:

“Although the GnuTLS library is thread safe by design, some parts of Libgcrypt, such as the random generator, are not. Applications have to register callback functions to ensure proper locking in the sensitive parts of libgcrypt.

There are helper macros to help you properly initialize the libraries. Examples are shown below.”

Three examples follow: For POSIX threads, GNU PTH threads and “other thread packages.” The problem is that the only exhaustive examples are the first two. The third is similar to this:

static struct gcry_thread_cbs gcry_threads_other = { ... };
int main()
{
	gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_other);
	gnutls_global_init();
}

Libgcrypt threading parameters are set before initializing GnuTLS, but any description about the content of gcry_threads_other is missing. The Libgcrypt documentation provides a bit more insight, but still no details. I looked at the gcrypt.h header and searched for other projects using gcry_thread_cbs. What I understood at this point is that the gcry_thread_cbs structure contains function pointers to functions that libgcrypt will use for mutex management.

The best reference code I found was from VLC. VLC uses it’s own thread implementation when pthreads are not available, and they set libgcrypt up to work with it. What I needed to do was to write functions for initializing, destroying, locking and unlocking a mutex. Each of these takes a void ** as parameter and returns an int that’s supposed to be zero if everything’s OK.

The solution was to write wrappers for the GMutex functions. The void ** has to contain a GMutex * and the return value is always 0. Then just create a gcry_thread_cbs that contains the right pointers and it’s done. Looks like this:

static int gthread_mutex_init(void **priv)
{
	*priv = g_mutex_new();
	return 0;
}

static int gthread_mutex_destroy(void **priv)
{
	g_mutex_free((GMutex *) (*priv));
	return 0;
}

static int gthread_mutex_lock(void **priv)
{
	g_mutex_lock((GMutex *) (*priv));
	return 0;
}

static int gthread_mutex_unlock(void **priv)
{
	g_mutex_unlock((GMutex *) (*priv));
	return 0;	
}

static const struct gcry_thread_cbs gcry_gthreads_cbs = {
	GCRY_THREAD_OPTION_USER,
	NULL,
	gthread_mutex_init,
	gthread_mutex_destroy,
	gthread_mutex_lock,
	gthread_mutex_unlock
};

And in main() right before initializing GnuTLS:

gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_gthreads_cbs);
Advertisements

Responses

  1. Helpful post, thank you. I know this article is quite old, but I have a question you may eventually help. My “gthread_mutex_destroy”-Method is never being called (the others are!). Do I have to unload something in my class destructor to get this working?


Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: