diff options
author | Stef Walter <stef@memberwebs.com> | 2010-07-29 16:34:07 +0200 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2010-07-29 16:34:07 +0200 |
commit | 102ced8f53dcccd2c42c8a89abea87b91f56e297 (patch) | |
tree | d37cfd33a900f734d061b1788d046448de5e73b9 /gck/gck-misc.c | |
parent | d7da07727afd570c5b655ba08471fa417f2bba64 (diff) | |
download | gcr-102ced8f53dcccd2c42c8a89abea87b91f56e297.tar.gz |
[gck] In preparation for public release, rename library.
* Next steps will include cleaning up the API making it ready
for gobject introspection etc..
Diffstat (limited to 'gck/gck-misc.c')
-rw-r--r-- | gck/gck-misc.c | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/gck/gck-misc.c b/gck/gck-misc.c new file mode 100644 index 0000000..ae8c66d --- /dev/null +++ b/gck/gck-misc.c @@ -0,0 +1,437 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* gck-misc.c - the GObject PKCS#11 wrapper library + + Copyright (C) 2008, 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 <nielsen@memberwebs.com> +*/ + +#include "config.h" + +#include "gck.h" +#include "gck-private.h" + +#include <glib/gi18n.h> + +/** + * SECTION:gck-error + * @title: Errors + * @short_description: Gck Errors and error codes. + * + * Errors are returned as GError structures. The code member of GError + * contains the raw PKCS11 CK_RV result value. + */ + +/** + * GCK_VENDOR_CODE: + * + * Custom PKCS11 errors that originate from the gck library, are + * based at this error code. + */ + +/** + * CKR_GCK_MODULE_PROBLEM: + * + * A result code that signifies there was a problem loading a PKCS11 + * module, usually a shared library. + * + * More details can be found in the error string. + */ + +/** + * GCK_ERROR: + * + * The error domain for gck library errors. + */ +GQuark +gck_get_error_quark (void) +{ + static GQuark domain = 0; + static volatile gsize quark_inited = 0; + + if (g_once_init_enter (&quark_inited)) { + domain = g_quark_from_static_string ("gck-error"); + g_once_init_leave (&quark_inited, 1); + } + + return domain; +} + +/** + * gck_message_from_rv: + * @rv: The PKCS#11 return value to get a message for. + * + * Get a message for a PKCS#11 return value or error code. Do not + * pass CKR_OK or other such non errors to this function. + * + * Return value: The user readable message. + **/ +const gchar* +gck_message_from_rv (CK_RV rv) +{ + switch (rv) { + + /* These are not really errors, or not current */ + case CKR_OK: + case CKR_NO_EVENT: + case CKR_FUNCTION_NOT_PARALLEL: + case CKR_SESSION_PARALLEL_NOT_SUPPORTED: + g_return_val_if_reached (""); + + case CKR_CANCEL: + case CKR_FUNCTION_CANCELED: + return _("The operation was cancelled"); + + case CKR_HOST_MEMORY: + return _("Insufficient memory available"); + case CKR_SLOT_ID_INVALID: + return _("The specified slot ID is not valid"); + case CKR_GENERAL_ERROR: + return _("Internal error"); + case CKR_FUNCTION_FAILED: + return _("The operation failed"); + case CKR_ARGUMENTS_BAD: + return _("Invalid arguments"); + case CKR_NEED_TO_CREATE_THREADS: + return _("The module cannot create needed threads"); + case CKR_CANT_LOCK: + return _("The module cannot lock data properly"); + case CKR_ATTRIBUTE_READ_ONLY: + return _("The field is read-only"); + case CKR_ATTRIBUTE_SENSITIVE: + return _("The field is sensitive and cannot be revealed"); + case CKR_ATTRIBUTE_TYPE_INVALID: + return _("The field is invalid or does not exist"); + case CKR_ATTRIBUTE_VALUE_INVALID: + return _("Invalid value for field"); + case CKR_DATA_INVALID: + return _("The data is not valid or unrecognized"); + case CKR_DATA_LEN_RANGE: + return _("The data is too long"); + case CKR_DEVICE_ERROR: + return _("An error occurred on the device"); + case CKR_DEVICE_MEMORY: + return _("Insufficient memory available on device"); + case CKR_DEVICE_REMOVED: + return _("The device was removed or unplugged"); + case CKR_ENCRYPTED_DATA_INVALID: + return _("The encrypted data is not valid or unrecognized"); + case CKR_ENCRYPTED_DATA_LEN_RANGE: + return _("The encrypted data is too long"); + case CKR_FUNCTION_NOT_SUPPORTED: + return _("This operation is not supported"); + case CKR_KEY_HANDLE_INVALID: + return _("The key is missing or invalid"); + case CKR_KEY_SIZE_RANGE: + return _("The key is the wrong size"); + case CKR_KEY_TYPE_INCONSISTENT: + return _("The key is of the wrong type"); + case CKR_KEY_NOT_NEEDED: + return _("No key is needed"); + case CKR_KEY_CHANGED: + return _("The key is different than before"); + case CKR_KEY_NEEDED: + return _("A key is needed"); + case CKR_KEY_INDIGESTIBLE: + return _("Cannot include the key in digest"); + case CKR_KEY_FUNCTION_NOT_PERMITTED: + return _("This operation cannot be done with this key"); + case CKR_KEY_NOT_WRAPPABLE: + return _("The key cannot be wrapped"); + case CKR_KEY_UNEXTRACTABLE: + return _("Cannot export this key"); + case CKR_MECHANISM_INVALID: + return _("The crypto mechanism is invalid or unrecognized"); + case CKR_MECHANISM_PARAM_INVALID: + return _("The crypto mechanism has an invalid argument"); + case CKR_OBJECT_HANDLE_INVALID: + return _("The object is missing or invalid"); + case CKR_OPERATION_ACTIVE: + return _("Another operation is already taking place"); + case CKR_OPERATION_NOT_INITIALIZED: + return _("No operation is taking place"); + case CKR_PIN_INCORRECT: + return _("The password or PIN is incorrect"); + case CKR_PIN_INVALID: + return _("The password or PIN is invalid"); + case CKR_PIN_LEN_RANGE: + return _("The password or PIN is of an invalid length"); + case CKR_PIN_EXPIRED: + return _("The password or PIN has expired"); + case CKR_PIN_LOCKED: + return _("The password or PIN is locked"); + case CKR_SESSION_CLOSED: + return _("The session is closed"); + case CKR_SESSION_COUNT: + return _("Too many sessions are active"); + case CKR_SESSION_HANDLE_INVALID: + return _("The session is invalid"); + case CKR_SESSION_READ_ONLY: + return _("The session is read-only"); + case CKR_SESSION_EXISTS: + return _("An open session exists"); + case CKR_SESSION_READ_ONLY_EXISTS: + return _("A read-only session exists"); + case CKR_SESSION_READ_WRITE_SO_EXISTS: + return _("An administrator session exists"); + case CKR_SIGNATURE_INVALID: + return _("The signature is bad or corrupted"); + case CKR_SIGNATURE_LEN_RANGE: + return _("The signature is unrecognized or corrupted"); + case CKR_TEMPLATE_INCOMPLETE: + return _("Certain required fields are missing"); + case CKR_TEMPLATE_INCONSISTENT: + return _("Certain fields have invalid values"); + case CKR_TOKEN_NOT_PRESENT: + return _("The device is not present or unplugged"); + case CKR_TOKEN_NOT_RECOGNIZED: + return _("The device is invalid or unrecognizable"); + case CKR_TOKEN_WRITE_PROTECTED: + return _("The device is write protected"); + case CKR_UNWRAPPING_KEY_HANDLE_INVALID: + return _("Cannot import because the key is invalid"); + case CKR_UNWRAPPING_KEY_SIZE_RANGE: + return _("Cannot import because the key is of the wrong size"); + case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: + return _("Cannot import because the key is of the wrong type"); + case CKR_USER_ALREADY_LOGGED_IN: + return _("You are already logged in"); + case CKR_USER_NOT_LOGGED_IN: + return _("No user has logged in"); + case CKR_USER_PIN_NOT_INITIALIZED: + return _("The user's password or PIN is not set"); + case CKR_USER_TYPE_INVALID: + return _("The user is of an invalid type"); + case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: + return _("Another user is already logged in"); + case CKR_USER_TOO_MANY_TYPES: + return _("Too many users of different types logged in"); + case CKR_WRAPPED_KEY_INVALID: + return _("Cannot import an invalid key"); + case CKR_WRAPPED_KEY_LEN_RANGE: + return _("Cannot import a key of the wrong size"); + case CKR_WRAPPING_KEY_HANDLE_INVALID: + return _("Cannot export because the key is invalid"); + case CKR_WRAPPING_KEY_SIZE_RANGE: + return _("Cannot export because the key is of the wrong size"); + case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: + return _("Cannot export because the key is of the wrong type"); + case CKR_RANDOM_SEED_NOT_SUPPORTED: + return _("Unable to initialize the random number generator"); + case CKR_RANDOM_NO_RNG: + return _("No random number generator available"); + case CKR_DOMAIN_PARAMS_INVALID: + return _("The crypto mechanism has an invalid parameter"); + case CKR_BUFFER_TOO_SMALL: + return _("Not enough space to store the result"); + case CKR_SAVED_STATE_INVALID: + return _("The saved state is invalid"); + case CKR_INFORMATION_SENSITIVE: + return _("The information is sensitive and cannot be revealed"); + case CKR_STATE_UNSAVEABLE: + return _("The state cannot be saved"); + case CKR_CRYPTOKI_NOT_INITIALIZED: + return _("The module has not been initialized"); + case CKR_CRYPTOKI_ALREADY_INITIALIZED: + return _("The module has already been initialized"); + case CKR_MUTEX_BAD: + return _("Cannot lock data"); + case CKR_MUTEX_NOT_LOCKED: + return _("The data cannot be locked"); + case CKR_FUNCTION_REJECTED: + return _("The signature request was rejected by the user"); + + default: + g_message ("unknown error: %lu", (gulong)rv); + return _("Unknown error"); + } +} + +/** + * SECTION:gck-misc + * @title: Miscellaneous Functions + * @short_description: Other miscellaneous functions. + * + * A few supporting functions that come in handy when dealing with the gck + * library or PKCS11 in general. + */ + +/** + * gck_list_unref_free: + * @reflist: List of Gobject reference counted pointers. + * + * Free a list of GObject based pointers. All objects in the list + * will be unreffed and then the list itself will be freed. + **/ +void +gck_list_unref_free (GList *reflist) +{ + GList *l; + for (l = reflist; l; l = g_list_next (l)) { + g_return_if_fail (G_IS_OBJECT (l->data)); + g_object_unref (l->data); + } + g_list_free (reflist); +} + +/** + * gck_list_ref_copy: + * @reflist: List of GObject reference counted objects. + * + * Copy a list of GObject based pointers. All objects + * in the list will be reffed and the list will be copied. + * + * Return value: The copied and reffed list. When done, free it with + * gck_list_unref_free () + **/ +GList* +gck_list_ref_copy (GList *reflist) +{ + GList *l, *copy = g_list_copy (reflist); + for (l = copy; l; l = g_list_next (l)) { + g_return_val_if_fail (G_IS_OBJECT (l->data), NULL); + g_object_ref (l->data); + } + return copy; +} + +/** + * gck_string_from_chars: + * @data: The character data to turn into a null terminated string. + * @max: The maximum length of the charater data. + * + * Create a string from a set of PKCS#11 characters. This is + * similar to g_strndup, except for that it also strips trailing + * spaces. These space padded strings are often used in PKCS#11 + * structures. + * + * Return value: The null terminated string. + */ +gchar* +gck_string_from_chars (const guchar *data, gsize max) +{ + gchar *string; + + g_return_val_if_fail (data, NULL); + g_return_val_if_fail (max, NULL); + + string = g_strndup ((gchar*)data, max); + g_strchomp (string); + return string; +} + +guint +_gck_ulong_hash (gconstpointer v) +{ + const signed char *p = v; + guint32 i, h = *p; + + for(i = 0; i < sizeof (gulong); ++i) + h = (h << 5) - h + *(p++); + + return h; +} + +gboolean +_gck_ulong_equal (gconstpointer v1, gconstpointer v2) +{ + return *((const gulong*)v1) == *((const gulong*)v2); +} + +static GQuark mechanism_quark = 0; + +static void +free_refs (gpointer data) +{ + gint *refs = data; + g_assert (refs); + g_assert (*refs == 0); + g_slice_free (gint, data); +} + +GckMechanism* +gck_mechanism_new (gulong type) +{ + return gck_mechanism_new_with_param (type, NULL, 0); +} + +GckMechanism* +gck_mechanism_new_with_param (gulong type, gconstpointer parameter, + gulong n_parameter) +{ + static volatile gsize inited_quark = 0; + GckMechanism *mech; + gint *refs; + + /* Initialize first time around */ + if (g_once_init_enter (&inited_quark)) { + mechanism_quark = g_quark_from_static_string ("GckMechanism::refs"); + g_once_init_leave (&inited_quark, 1); + } + + mech = g_slice_new (GckMechanism); + mech->type = type; + mech->parameter = g_memdup (parameter, n_parameter); + mech->n_parameter = n_parameter; + + refs = g_slice_new (gint); + *refs = 1; + g_dataset_id_set_data_full (mech, mechanism_quark, refs, free_refs); + + return mech; +} + +GckMechanism* +gck_mechanism_ref (GckMechanism* mech) +{ + gint *refs; + + g_return_val_if_fail (mech, NULL); + + refs = g_dataset_id_get_data (mech, mechanism_quark); + if (refs == NULL) { + g_warning ("Encountered invalid GckMechanism struct. Either it was unreffed or " + "possibly allocated on the stack. Always use gck_mechanism_new () and friends."); + return NULL; + } + + g_atomic_int_add (refs, 1); + return mech; +} + +void +gck_mechanism_unref (GckMechanism* mech) +{ + gint *refs; + + if (!mech) + return; + + refs = g_dataset_id_get_data (mech, mechanism_quark); + if (refs == NULL) { + g_warning ("Encountered invalid GckMechanism struct. Either it was unreffed or " + "possibly allocated on the stack. Always use gck_mechanism_new () and friends."); + return; + } + + if (g_atomic_int_dec_and_test (refs)) { + g_free (mech->parameter); + g_dataset_id_remove_data (mech, mechanism_quark); + g_slice_free (GckMechanism, mech); + } +} |