1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gck-misc.c - the GObject PKCS#11 wrapper library
3 
4    Copyright (C) 2008, Stefan Walter
5 
6    The Gnome Keyring Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10 
11    The Gnome Keyring Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with the Gnome Library; see the file COPYING.LIB.  If not,
18    see <http://www.gnu.org/licenses/>.
19 
20    Author: Stef Walter <nielsen@memberwebs.com>
21 */
22 
23 #include "config.h"
24 
25 #include "gck.h"
26 #include "gck-private.h"
27 
28 #include "egg/egg-secure-memory.h"
29 
30 #include <p11-kit/p11-kit.h>
31 
32 #include <glib/gi18n-lib.h>
33 
34 #include <string.h>
35 
36 EGG_SECURE_DEFINE_GLIB_GLOBALS ();
37 
38 /**
39  * SECTION:gck-library
40  * @title: Library Utilities
41  * @short_description: Library utilities such as version checks
42  *
43  * Basic library utilities such as version checks.
44  */
45 
46 /**
47  * GCK_CHECK_VERSION:
48  * @major: the major version to check for
49  * @minor: the minor version to check for
50  * @micro: the micro version to check for
51  *
52  * Checks the version of the Gck libarry that is being compiled
53  * against.
54  *
55  * <example>
56  * <title>Checking the version of the Gck library</title>
57  * <programlisting>
58  * #if !GCK_CHECK_VERSION (3, 0, 0)
59  * #warning Old Gck version, disabling functionality
60  * #endif
61  * </programlisting>
62  * </example>
63  *
64  * Returns: %TRUE if the version of the GLib header files
65  * is the same as or newer than the passed-in version.
66  */
67 
68 /**
69  * GCK_MAJOR_VERSION:
70  *
71  * The major version number of the Gck library.
72  */
73 
74 /**
75  * GCK_MINOR_VERSION:
76  *
77  * The minor version number of the Gck library.
78  */
79 
80 /**
81  * GCK_MICRO_VERSION:
82  *
83  * The micro version number of the Gck library.
84  */
85 
86 /**
87  * SECTION:gck-error
88  * @title: Errors
89  * @short_description: Gck Errors and error codes.
90  *
91  * Errors are returned as GError structures. The code member of GError
92  * contains the raw PKCS11 CK_RV result value.
93  */
94 
95 /**
96  * SECTION:gck-private
97  * @title: Private, not used in docs
98  * @short_description: Should not show up in docs
99  *
100  * Should not show up in the docs
101  */
102 
103 /**
104  * GCK_INVALID:
105  *
106  * Used as a terminator at the end of variable argument lists.
107  */
108 
109 /**
110  * GCK_VENDOR_CODE:
111  *
112  * Custom PKCS11 errors that originate from the gck library, are
113  * based at this error code.
114  */
115 
116 /**
117  * GckError:
118  * @GCK_ERROR_MODULE_PROBLEM: a result code that signifies there was a problem
119  *                            loading a PKCS\#11 module, usually a shared library
120  *
121  * Various error codes. All the CKR_XXX error codes from PKCS\#11 are also
122  * relevant error codes.
123  */
124 
125 /**
126  * GCK_ERROR:
127  *
128  * The error domain for gck library errors.
129  */
130 
131 GQuark
gck_get_error_quark(void)132 gck_get_error_quark (void)
133 {
134 	/* This is the deprecated version */
135 	return gck_error_get_quark ();
136 }
137 
138 GQuark
gck_error_get_quark(void)139 gck_error_get_quark (void)
140 {
141 	static GQuark domain = 0;
142 	static volatile gsize quark_inited = 0;
143 
144 	if (g_once_init_enter (&quark_inited)) {
145 		domain = g_quark_from_static_string ("gck-error");
146 		g_once_init_leave (&quark_inited, 1);
147 	}
148 
149 	return domain;
150 }
151 
152 /**
153  * gck_message_from_rv:
154  * @rv: The PKCS\#11 return value to get a message for.
155  *
156  * Get a message for a PKCS\#11 return value or error code. Do not
157  * pass CKR_OK or other such non errors to this function.
158  *
159  * Return value: The user readable message.
160  **/
161 const gchar*
gck_message_from_rv(gulong rv)162 gck_message_from_rv (gulong rv)
163 {
164 	switch (rv) {
165 
166 	/* These are not really errors, or not current */
167 	case CKR_OK:
168 	case CKR_NO_EVENT:
169 	case CKR_FUNCTION_NOT_PARALLEL:
170 	case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
171 		g_return_val_if_reached ("");
172 
173 	default:
174 		return p11_kit_strerror (rv);
175 	}
176 }
177 
178 const gchar *
_gck_stringize_rv(CK_RV rv)179 _gck_stringize_rv (CK_RV rv)
180 {
181 	switch(rv) {
182 	#define X(x) case x: return #x;
183 	X (CKR_OK)
184 	X (CKR_CANCEL)
185 	X (CKR_HOST_MEMORY)
186 	X (CKR_SLOT_ID_INVALID)
187 	X (CKR_GENERAL_ERROR)
188 	X (CKR_FUNCTION_FAILED)
189 	X (CKR_ARGUMENTS_BAD)
190 	X (CKR_NO_EVENT)
191 	X (CKR_NEED_TO_CREATE_THREADS)
192 	X (CKR_CANT_LOCK)
193 	X (CKR_ATTRIBUTE_READ_ONLY)
194 	X (CKR_ATTRIBUTE_SENSITIVE)
195 	X (CKR_ATTRIBUTE_TYPE_INVALID)
196 	X (CKR_ATTRIBUTE_VALUE_INVALID)
197 	X (CKR_DATA_INVALID)
198 	X (CKR_DATA_LEN_RANGE)
199 	X (CKR_DEVICE_ERROR)
200 	X (CKR_DEVICE_MEMORY)
201 	X (CKR_DEVICE_REMOVED)
202 	X (CKR_ENCRYPTED_DATA_INVALID)
203 	X (CKR_ENCRYPTED_DATA_LEN_RANGE)
204 	X (CKR_FUNCTION_CANCELED)
205 	X (CKR_FUNCTION_NOT_PARALLEL)
206 	X (CKR_FUNCTION_NOT_SUPPORTED)
207 	X (CKR_KEY_HANDLE_INVALID)
208 	X (CKR_KEY_SIZE_RANGE)
209 	X (CKR_KEY_TYPE_INCONSISTENT)
210 	X (CKR_KEY_NOT_NEEDED)
211 	X (CKR_KEY_CHANGED)
212 	X (CKR_KEY_NEEDED)
213 	X (CKR_KEY_INDIGESTIBLE)
214 	X (CKR_KEY_FUNCTION_NOT_PERMITTED)
215 	X (CKR_KEY_NOT_WRAPPABLE)
216 	X (CKR_KEY_UNEXTRACTABLE)
217 	X (CKR_MECHANISM_INVALID)
218 	X (CKR_MECHANISM_PARAM_INVALID)
219 	X (CKR_OBJECT_HANDLE_INVALID)
220 	X (CKR_OPERATION_ACTIVE)
221 	X (CKR_OPERATION_NOT_INITIALIZED)
222 	X (CKR_PIN_INCORRECT)
223 	X (CKR_PIN_INVALID)
224 	X (CKR_PIN_LEN_RANGE)
225 	X (CKR_PIN_EXPIRED)
226 	X (CKR_PIN_LOCKED)
227 	X (CKR_SESSION_CLOSED)
228 	X (CKR_SESSION_COUNT)
229 	X (CKR_SESSION_HANDLE_INVALID)
230 	X (CKR_SESSION_PARALLEL_NOT_SUPPORTED)
231 	X (CKR_SESSION_READ_ONLY)
232 	X (CKR_SESSION_EXISTS)
233 	X (CKR_SESSION_READ_ONLY_EXISTS)
234 	X (CKR_SESSION_READ_WRITE_SO_EXISTS)
235 	X (CKR_SIGNATURE_INVALID)
236 	X (CKR_SIGNATURE_LEN_RANGE)
237 	X (CKR_TEMPLATE_INCOMPLETE)
238 	X (CKR_TEMPLATE_INCONSISTENT)
239 	X (CKR_TOKEN_NOT_PRESENT)
240 	X (CKR_TOKEN_NOT_RECOGNIZED)
241 	X (CKR_TOKEN_WRITE_PROTECTED)
242 	X (CKR_UNWRAPPING_KEY_HANDLE_INVALID)
243 	X (CKR_UNWRAPPING_KEY_SIZE_RANGE)
244 	X (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT)
245 	X (CKR_USER_ALREADY_LOGGED_IN)
246 	X (CKR_USER_NOT_LOGGED_IN)
247 	X (CKR_USER_PIN_NOT_INITIALIZED)
248 	X (CKR_USER_TYPE_INVALID)
249 	X (CKR_USER_ANOTHER_ALREADY_LOGGED_IN)
250 	X (CKR_USER_TOO_MANY_TYPES)
251 	X (CKR_WRAPPED_KEY_INVALID)
252 	X (CKR_WRAPPED_KEY_LEN_RANGE)
253 	X (CKR_WRAPPING_KEY_HANDLE_INVALID)
254 	X (CKR_WRAPPING_KEY_SIZE_RANGE)
255 	X (CKR_WRAPPING_KEY_TYPE_INCONSISTENT)
256 	X (CKR_RANDOM_SEED_NOT_SUPPORTED)
257 	X (CKR_RANDOM_NO_RNG)
258 	X (CKR_DOMAIN_PARAMS_INVALID)
259 	X (CKR_BUFFER_TOO_SMALL)
260 	X (CKR_SAVED_STATE_INVALID)
261 	X (CKR_INFORMATION_SENSITIVE)
262 	X (CKR_STATE_UNSAVEABLE)
263 	X (CKR_CRYPTOKI_NOT_INITIALIZED)
264 	X (CKR_CRYPTOKI_ALREADY_INITIALIZED)
265 	X (CKR_MUTEX_BAD)
266 	X (CKR_MUTEX_NOT_LOCKED)
267 	X (CKR_FUNCTION_REJECTED)
268 	X (CKR_VENDOR_DEFINED)
269 	#undef X
270 	default:
271 		return "CKR_??????";
272 	}
273 }
274 
275 CK_RV
_gck_rv_from_error(GError * error,CK_RV catch_all_code)276 _gck_rv_from_error (GError *error,
277                     CK_RV catch_all_code)
278 {
279 	g_return_val_if_fail (error != NULL, CKR_GENERAL_ERROR);
280 
281 	if (error->domain == GCK_ERROR)
282 		return error->code;
283 
284 	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
285 		return CKR_FUNCTION_CANCELED;
286 
287 	return catch_all_code;
288 }
289 
290 /**
291  * SECTION:gck-misc
292  * @title: Miscellaneous Functions
293  * @short_description: Other miscellaneous functions.
294  *
295  * A few supporting functions that come in handy when dealing with the gck
296  * library or PKCS11 in general.
297  */
298 
299 GType
gck_list_get_boxed_type(void)300 gck_list_get_boxed_type (void)
301 {
302 	static GType type = 0;
303 	if (!type)
304 		type = g_boxed_type_register_static ("GckList",
305 		                                     (GBoxedCopyFunc)gck_list_ref_copy,
306 		                                     (GBoxedFreeFunc)gck_list_unref_free);
307 	return type;
308 
309 }
310 
311 /**
312  * gck_list_unref_free: (skip)
313  * @reflist: (element-type GObject.Object): list of Gobject reference counted pointers
314  *
315  * Free a list of GObject based pointers. All objects in the list
316  * will be unreffed and then the list itself will be freed.
317  **/
318 void
gck_list_unref_free(GList * reflist)319 gck_list_unref_free (GList *reflist)
320 {
321 	GList *l;
322 	for (l = reflist; l; l = g_list_next (l)) {
323 		g_return_if_fail (G_IS_OBJECT (l->data));
324 		g_object_unref (l->data);
325 	}
326 	g_list_free (reflist);
327 }
328 
329 /**
330  * gck_list_ref_copy: (skip)
331  * @reflist: (element-type GObject.Object): list of GObject reference counted
332  *           objects
333  *
334  * Copy a list of GObject based pointers. All objects
335  * in the list will be reffed and the list will be copied.
336  *
337  * Return value: (transfer full) (element-type GObject.Object): the copied and
338  *               reffed list, when done, free it with gck_list_unref_free ()
339  **/
340 GList *
gck_list_ref_copy(GList * reflist)341 gck_list_ref_copy (GList *reflist)
342 {
343 	GList *l, *copy = g_list_copy (reflist);
344 	for (l = copy; l; l = g_list_next (l)) {
345 		g_return_val_if_fail (G_IS_OBJECT (l->data), NULL);
346 		g_object_ref (l->data);
347 	}
348 	return copy;
349 }
350 
351 /**
352  * gck_string_from_chars: (skip)
353  * @data: The character data to turn into a null terminated string.
354  * @max: The maximum length of the charater data.
355  *
356  * Create a string from a set of PKCS\#11 characters. This is
357  * similar to g_strndup, except for that it also strips trailing
358  * spaces. These space padded strings are often used in PKCS\#11
359  * structures.
360  *
361  * If the space padded string is filled with null characters then
362  * this function will return %NULL.
363  *
364  * Return value: The null terminated string.
365  */
366 gchar*
gck_string_from_chars(const guchar * data,gsize max)367 gck_string_from_chars (const guchar *data, gsize max)
368 {
369 	gchar *string;
370 
371 	g_return_val_if_fail (data, NULL);
372 	g_return_val_if_fail (max, NULL);
373 
374 	/* Means no value */
375 	if (!data[0])
376 		return NULL;
377 
378 	string = g_strndup ((gchar*)data, max);
379 	g_strchomp (string);
380 	return string;
381 }
382 
383 /**
384  * gck_string_to_chars: (skip)
385  * @data: The character buffer to place string into.
386  * @max: The maximum length of the charater buffer.
387  * @string: The string to place in the buffer.
388  *
389  * Create a space padded PKCS\#11 string from a null terminated string.
390  * The string must be shorter than the buffer or %FALSE will be
391  * returned.
392  *
393  * If a %NULL string is passed, then the space padded string will be
394  * set to zero characters.
395  *
396  * Return value: The null terminated string.
397  */
398 gboolean
gck_string_to_chars(guchar * data,gsize max,const gchar * string)399 gck_string_to_chars (guchar *data, gsize max, const gchar *string)
400 {
401 	gsize len;
402 
403 	g_return_val_if_fail (data, FALSE);
404 	g_return_val_if_fail (max, FALSE);
405 
406 	if (!string) {
407 		memset (data, 0, max);
408 		return TRUE;
409 	}
410 
411 	len = strlen (string);
412 	if (len > max)
413 		return FALSE;
414 
415 	memset (data, ' ', max);
416 	memcpy (data, string, len);
417 	return TRUE;
418 }
419 
420 guint
_gck_ulong_hash(gconstpointer v)421 _gck_ulong_hash (gconstpointer v)
422 {
423 	const signed char *p = v;
424 	guint32 i, h = *p;
425 
426 	for(i = 0; i < sizeof (gulong); ++i)
427 		h = (h << 5) - h + *(p++);
428 
429 	return h;
430 }
431 
432 gboolean
_gck_ulong_equal(gconstpointer v1,gconstpointer v2)433 _gck_ulong_equal (gconstpointer v1, gconstpointer v2)
434 {
435 	return memcmp(v1, v2, sizeof (gulong)) == 0;
436 }
437 
438 /**
439  * gck_value_to_ulong:
440  * @value: (array length=length): memory to convert
441  * @length: length of memory
442  * @result: A location to store the result
443  *
444  * Convert CK_ULONG type memory to a boolean.
445  *
446  * Returns: Whether the conversion was successful.
447  */
448 gboolean
gck_value_to_ulong(const guchar * value,gsize length,gulong * result)449 gck_value_to_ulong (const guchar *value,
450                     gsize length,
451                     gulong *result)
452 {
453 	if (!value || length != sizeof (CK_ULONG))
454 		return FALSE;
455 	if (result)
456 		memcpy(result, value, sizeof(CK_ULONG));
457 	return TRUE;
458 }
459 
460 /**
461  * gck_value_to_boolean:
462  * @value: (array length=length): memory to convert
463  * @length: length of memory
464  * @result: A location to store the result
465  *
466  * Convert CK_BBOOL type memory to a boolean.
467  *
468  * Returns: Whether the conversion was successful.
469  */
470 gboolean
gck_value_to_boolean(const guchar * value,gsize length,gboolean * result)471 gck_value_to_boolean (const guchar *value,
472                       gsize length,
473                       gboolean *result)
474 {
475 	CK_BBOOL tempval = CK_FALSE;
476 	if (!value || length != sizeof (CK_BBOOL))
477 		return FALSE;
478 	if (result) {
479 		memcpy(&tempval, value, sizeof(CK_BBOOL));
480 		*result = tempval ? TRUE : FALSE;
481 	}
482 	return TRUE;
483 }
484 
485 static gboolean
match_info_string(const gchar * match,const gchar * string)486 match_info_string (const gchar *match, const gchar *string)
487 {
488 	/* NULL matches anything */
489 	if (match == NULL)
490 		return TRUE;
491 
492 	if (string == NULL)
493 		return FALSE;
494 
495 	return g_str_equal (match, string);
496 }
497 
498 gboolean
_gck_module_info_match(GckModuleInfo * match,GckModuleInfo * info)499 _gck_module_info_match (GckModuleInfo *match, GckModuleInfo *info)
500 {
501 	/* Matches two GckModuleInfo for use in PKCS#11 URI's */
502 
503 	g_return_val_if_fail (match, FALSE);
504 	g_return_val_if_fail (info, FALSE);
505 
506 	return (match_info_string (match->library_description, info->library_description) &&
507 	        match_info_string (match->manufacturer_id, info->manufacturer_id));
508 }
509 
510 gboolean
_gck_token_info_match(GckTokenInfo * match,GckTokenInfo * info)511 _gck_token_info_match (GckTokenInfo *match, GckTokenInfo *info)
512 {
513 	/* Matches two GckTokenInfo for use in PKCS#11 URI's */
514 
515 	g_return_val_if_fail (match, FALSE);
516 	g_return_val_if_fail (info, FALSE);
517 
518 	return (match_info_string (match->label, info->label) &&
519 	        match_info_string (match->manufacturer_id, info->manufacturer_id) &&
520 	        match_info_string (match->model, info->model) &&
521 	        match_info_string (match->serial_number, info->serial_number));
522 }
523