/** * 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; }
/** * 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; }
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; }
/** * 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; }
/** * 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; }
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; }
/** * 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); }
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; }
/** * 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); }
/** * 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; }
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); }
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; }
/** * 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; }
/** * 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; }