CK_RV gkm_module_C_GetSlotInfo (GkmModule *self, CK_SLOT_ID id, CK_SLOT_INFO_PTR info) { const CK_SLOT_INFO *original; GkmModuleClass *klass; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); if (id != GKM_SLOT_ID) return CKR_SLOT_ID_INVALID; if (info == NULL) return CKR_ARGUMENTS_BAD; /* Any slot ID is valid for partitioned module */ klass = GKM_MODULE_GET_CLASS (self); g_return_val_if_fail (klass, CKR_GENERAL_ERROR); g_return_val_if_fail (klass->get_slot_info, CKR_GENERAL_ERROR); original = (klass->get_slot_info) (self); g_return_val_if_fail (original, CKR_GENERAL_ERROR); memcpy (info, original, sizeof (CK_SLOT_INFO)); /* Extend all the strings appropriately */ extend_space_string (info->manufacturerID, sizeof (info->manufacturerID)); extend_space_string (info->slotDescription, sizeof (info->slotDescription)); return CKR_OK; }
CK_RV gkm_module_C_CloseAllSessions (GkmModule *self, CK_SLOT_ID id) { Apartment *apt; CK_SESSION_HANDLE handle; GList *l; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); if (APARTMENT_SLOT (id) != GKM_SLOT_ID) return CKR_SLOT_ID_INVALID; apt = lookup_apartment (self, id); if (apt == NULL) return CKR_OK; /* Unregister all its sessions */ for (l = apt->sessions; l; l = g_list_next (l)) { handle = gkm_session_get_handle (l->data); if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle)) g_assert_not_reached (); } unregister_apartment (self, apt); return CKR_OK; }
CK_RV gkm_module_login_so (GkmModule *self, CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin) { g_return_val_if_fail (GKM_IS_MODULE (self), CKR_GENERAL_ERROR); g_assert (GKM_MODULE_GET_CLASS (self)->login_so); return GKM_MODULE_GET_CLASS (self)->login_so (self, slot_id, pin, n_pin); }
CK_RV gkm_module_C_GetMechanismInfo (GkmModule *self, CK_SLOT_ID id, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR info) { const guint n_mechanisms = G_N_ELEMENTS (mechanism_list); guint index; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); if (id != GKM_SLOT_ID) return CKR_SLOT_ID_INVALID; if (info == NULL) return CKR_ARGUMENTS_BAD; for (index = 0; index < n_mechanisms; ++index) { if (mechanism_list[index].mechanism == type) break; } if (index == n_mechanisms) return CKR_MECHANISM_INVALID; memcpy (info, &mechanism_list[index].info, sizeof (CK_MECHANISM_INFO)); return CKR_OK; }
CK_RV gkm_module_C_CloseSession (GkmModule *self, CK_SESSION_HANDLE handle) { GkmSession *session; CK_ULONG apt_id; Apartment *apt; GList *link; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); session = gkm_module_lookup_session (self, handle); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; /* Calculate the virtual slot */ apt_id = gkm_session_get_apartment (session); apt = lookup_apartment (self, apt_id); g_return_val_if_fail (apt, CKR_GENERAL_ERROR); link = g_list_find (apt->sessions, session); g_return_val_if_fail (link, CKR_GENERAL_ERROR); apt->sessions = g_list_delete_link (apt->sessions, link); g_object_unref (session); if (!apt->sessions) unregister_apartment (self, apt); if (!g_hash_table_remove (self->pv->sessions_by_handle, &handle)) g_assert_not_reached (); return CKR_OK; }
CK_RV gkm_module_C_GetMechanismList (GkmModule *self, CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mech_list, CK_ULONG_PTR count) { const guint n_mechanisms = G_N_ELEMENTS (mechanism_list); guint i; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); if (id != GKM_SLOT_ID) return CKR_SLOT_ID_INVALID; if (count == NULL) return CKR_ARGUMENTS_BAD; /* Just want to get the count */ if (mech_list == NULL) { *count = n_mechanisms; return CKR_OK; } /* Buffer too small? */ if (*count < n_mechanisms) { *count = n_mechanisms; return CKR_BUFFER_TOO_SMALL; } *count = n_mechanisms; for (i = 0; i < n_mechanisms; ++i) mech_list[i] = mechanism_list[i].mechanism; return CKR_OK; }
GkmModule* gkm_object_get_module (GkmObject *self) { g_return_val_if_fail (GKM_IS_OBJECT (self), NULL); g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL); return self->pv->module; }
static void gkm_object_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec) { GkmObject *self = GKM_OBJECT (obj); switch (prop_id) { case PROP_HANDLE: g_value_set_ulong (value, gkm_object_get_handle (self)); break; case PROP_MODULE: g_return_if_fail (GKM_IS_MODULE (self->pv->module)); g_value_set_object (value, gkm_object_get_module (self)); break; case PROP_MANAGER: g_value_set_object (value, gkm_object_get_manager (self)); break; case PROP_STORE: g_value_set_object (value, self->pv->store); break; case PROP_UNIQUE: g_value_set_string (value, gkm_object_get_unique (self)); break; case PROP_TRANSIENT: g_value_set_boolean (value, gkm_object_is_transient (self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } }
CK_RV gkm_module_C_Logout (GkmModule *self, CK_SESSION_HANDLE handle) { CK_ULONG apt_id; Apartment *apt; GkmSession *session; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); session = gkm_module_lookup_session (self, handle); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; apt_id = gkm_session_get_apartment (session); apt = lookup_apartment (self, apt_id); g_return_val_if_fail (apt, CKR_GENERAL_ERROR); if (apt->logged_in == CKU_NONE) return CKR_USER_NOT_LOGGED_IN; else if (apt->logged_in == CKU_USER) return gkm_module_logout_user (self, apt_id); else if (apt->logged_in == CKU_SO) return gkm_module_logout_so (self, apt_id); else g_return_val_if_reached (CKR_GENERAL_ERROR); }
CK_RV gkm_module_C_InitPIN (GkmModule* self, CK_SESSION_HANDLE handle, CK_UTF8CHAR_PTR pin, CK_ULONG n_pin) { GkmSession *session; Apartment *apt; CK_ULONG apt_id; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); session = gkm_module_lookup_session (self, handle); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; /* Calculate the virtual slot */ apt_id = gkm_session_get_apartment (session); apt = lookup_apartment (self, apt_id); g_return_val_if_fail (apt, CKR_GENERAL_ERROR); if (apt->logged_in != CKU_SO) return CKR_USER_NOT_LOGGED_IN; /* Our InitPIN assumes an uninitialized PIN */ return gkm_module_login_change (self, apt_id, NULL, 0, pin, n_pin); }
CK_RV gkm_module_logout_so (GkmModule *self, CK_SLOT_ID slot_id) { g_return_val_if_fail (GKM_IS_MODULE (self), CKR_GENERAL_ERROR); g_assert (GKM_MODULE_GET_CLASS (self)->logout_so); return GKM_MODULE_GET_CLASS (self)->logout_so (self, slot_id); }
GkmManager* gkm_module_get_manager (GkmModule *self) { g_return_val_if_fail (GKM_IS_MODULE (self), NULL); g_return_val_if_fail (GKM_IS_MANAGER (self->pv->token_manager), NULL); return self->pv->token_manager; }
CK_RV gkm_module_refresh_token (GkmModule *self) { g_return_val_if_fail (GKM_IS_MODULE (self), CKR_GENERAL_ERROR); g_assert (GKM_MODULE_GET_CLASS (self)->refresh_token); return GKM_MODULE_GET_CLASS (self)->refresh_token (self); }
GkmFactory* gkm_module_find_factory (GkmModule *self, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { GkmFactory *factory; gboolean matched; gulong j; gsize i; g_return_val_if_fail (GKM_IS_MODULE (self), NULL); g_return_val_if_fail (attrs || !n_attrs, NULL); if (!self->pv->factories_sorted) { g_array_sort (self->pv->factories, sort_factory_by_n_attrs); self->pv->factories_sorted = TRUE; } for (i = 0; i < self->pv->factories->len; ++i) { factory = &(g_array_index (self->pv->factories, GkmFactory, i)); matched = TRUE; for (j = 0; j < factory->n_attrs; ++j) { if (!gkm_attributes_contains (attrs, n_attrs, &factory->attrs[j])) { matched = FALSE; break; } } if (matched) return factory; } return NULL; }
CK_RV gkm_module_C_GetSlotList (GkmModule *self, CK_BBOOL token_present, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count) { g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); if (!count) return CKR_ARGUMENTS_BAD; /* Just want to get the count */ if (slot_list == NULL) { *count = 1; return CKR_OK; } /* Buffer too small? */ if (*count == 0) { *count = 1; return CKR_BUFFER_TOO_SMALL; } g_return_val_if_fail (slot_list, CKR_ARGUMENTS_BAD); /* Answer C_GetSlotList with 0 for app */ slot_list[0] = GKM_SLOT_ID; *count = 1; return CKR_OK; }
static void unregister_apartment (GkmModule *self, Apartment *apt) { g_assert (apt); g_assert (GKM_IS_MODULE (self)); if (!g_hash_table_remove (self->pv->apartments_by_id, &(apt->apt_id))) g_assert_not_reached (); }
static void register_apartment (GkmModule *self, Apartment *apt) { g_assert (apt); g_assert (GKM_IS_MODULE (self)); g_assert (!g_hash_table_lookup (self->pv->apartments_by_id, &(apt->apt_id))); g_hash_table_insert (self->pv->apartments_by_id, gkm_util_ulong_alloc (apt->apt_id), apt); }
static GObject* gkm_object_constructor (GType type, guint n_props, GObjectConstructParam *props) { GkmObject *self = GKM_OBJECT (G_OBJECT_CLASS (gkm_object_parent_class)->constructor(type, n_props, props)); g_return_val_if_fail (self, NULL); g_return_val_if_fail (GKM_IS_MODULE (self->pv->module), NULL); return G_OBJECT (self); }
void gkm_module_store_token_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object) { g_return_if_fail (GKM_IS_MODULE (self)); g_return_if_fail (GKM_IS_OBJECT (object)); g_assert (GKM_MODULE_GET_CLASS (self)->store_token_object); if (!gkm_object_is_transient (object)) GKM_MODULE_GET_CLASS (self)->store_token_object (self, transaction, object); }
CK_ULONG gkm_module_next_handle (GkmModule *self) { g_return_val_if_fail (GKM_IS_MODULE (self), 0); if (self->pv->handle_counter == CK_MATE_MAX_HANDLE) { g_warning ("handle counter wrapped"); self->pv->handle_counter = 0; } return (self->pv->handle_counter)++; }
GkmXdgTrust* gkm_xdg_trust_create_for_assertion (GkmModule *module, GkmManager *manager, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { CK_ATTRIBUTE_PTR serial, issuer, cert; GkmXdgTrust *trust; g_return_val_if_fail (GKM_IS_MODULE (module), NULL); g_return_val_if_fail (GKM_IS_MANAGER (manager), NULL); g_return_val_if_fail (attrs || !n_attrs, NULL); serial = gkm_attributes_find (attrs, n_attrs, CKA_SERIAL_NUMBER); issuer = gkm_attributes_find (attrs, n_attrs, CKA_ISSUER); cert = gkm_attributes_find (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE); /* A trust object with just serial + issuer */ if (serial != NULL && issuer != NULL) { if (cert != NULL) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT); return NULL; } if (!validate_der (issuer, "Name") || !validate_integer (serial)) { gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID); return NULL; } trust = create_trust_for_reference (module, manager, serial, issuer); /* A trust object with a full certificate */ } else if (cert != NULL) { if (serial != NULL || issuer != NULL) { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCONSISTENT); return NULL; } if (!validate_der (cert, "Certificate")) { gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID); return NULL; } trust = create_trust_for_complete (module, manager, cert); /* Not sure what this is */ } else { gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE); return NULL; } gkm_attributes_consume (attrs, n_attrs, CKA_X_CERTIFICATE_VALUE, CKA_ISSUER, CKA_SERIAL_NUMBER, G_MAXULONG); return trust; }
void gkm_module_register_factory (GkmModule *self, GkmFactory *factory) { g_return_if_fail (GKM_IS_MODULE (self)); g_return_if_fail (factory); g_return_if_fail (factory->attrs || !factory->n_attrs); g_return_if_fail (factory->func); g_array_append_val (self->pv->factories, *factory); self->pv->factories_sorted = FALSE; }
static void gkm_object_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { GkmObject *self = GKM_OBJECT (obj); GkmStore *store; switch (prop_id) { case PROP_HANDLE: gkm_object_set_handle (self, g_value_get_ulong (value)); break; case PROP_MODULE: g_return_if_fail (!self->pv->module); self->pv->module = g_value_get_object (value); g_return_if_fail (GKM_IS_MODULE (self->pv->module)); g_object_weak_ref (G_OBJECT (self->pv->module), module_went_away, self); break; case PROP_MANAGER: g_return_if_fail (!self->pv->manager); self->pv->manager = g_value_get_object (value); if (self->pv->manager) { g_object_add_weak_pointer (G_OBJECT (self->pv->manager), (gpointer*)&(self->pv->manager)); } break; case PROP_STORE: store = g_value_get_object (value); if (self->pv->store) { g_return_if_fail (!store); g_object_remove_weak_pointer (G_OBJECT (self->pv->store), (gpointer*)&(self->pv->store)); } self->pv->store = store; if (self->pv->store) g_object_add_weak_pointer (G_OBJECT (self->pv->store), (gpointer*)&(self->pv->store)); g_object_notify (G_OBJECT (self), "store"); break; case PROP_UNIQUE: g_return_if_fail (!self->pv->unique); self->pv->unique = g_value_dup_string (value); break; case PROP_TRANSIENT: g_return_if_fail (!self->pv->transient); if (g_value_get_boolean (value)) mark_object_transient (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } }
static void mark_login_apartment (GkmModule *self, Apartment *apt, CK_USER_TYPE user) { GList *l; g_assert (apt); g_assert (GKM_IS_MODULE (self)); /* Mark all sessions in the partition as logged in */ for (l = apt->sessions; l; l = g_list_next (l)) gkm_session_set_logged_in (l->data, user); apt->logged_in = user; }
gboolean gkm_module_get_write_protected (GkmModule *self) { const CK_TOKEN_INFO* info; g_return_val_if_fail (GKM_IS_MODULE (self), TRUE); g_return_val_if_fail (GKM_MODULE_GET_CLASS (self)->get_token_info, TRUE); info = (GKM_MODULE_GET_CLASS (self)->get_token_info) (self); g_return_val_if_fail (info, TRUE); return info->flags & CKF_WRITE_PROTECTED; }
CK_RV gkm_module_C_Login (GkmModule *self, CK_SESSION_HANDLE handle, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { CK_ULONG apt_id; GkmSession *session; Apartment *apt; GList *l; g_return_val_if_fail (GKM_IS_MODULE (self), CKR_CRYPTOKI_NOT_INITIALIZED); session = gkm_module_lookup_session (self, handle); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; /* Pass off context specifc logins to appropriate place */ if (user_type == CKU_CONTEXT_SPECIFIC) return gkm_session_login_context_specific (session, pin, pin_len); /* Some random crap... */ if (user_type != CKU_USER && user_type != CKU_SO) return CKR_USER_TYPE_INVALID; /* Calculate the virtual slot */ apt_id = gkm_session_get_apartment (session); apt = lookup_apartment (self, apt_id); g_return_val_if_fail (apt, CKR_GENERAL_ERROR); if (apt->logged_in == user_type) return CKR_USER_ALREADY_LOGGED_IN; if (apt->logged_in != CKU_NONE) return CKR_USER_ANOTHER_ALREADY_LOGGED_IN; if (user_type == CKU_SO) { /* Can't login as SO if read-only sessions exist */ for (l = apt->sessions; l; l = g_list_next (l)) { if (gkm_session_get_read_only (l->data)) return CKR_SESSION_READ_ONLY_EXISTS; } return gkm_module_login_so (self, apt_id, pin, pin_len); } else if (user_type == CKU_USER) { return gkm_module_login_user (self, apt_id, pin, pin_len); } else { return CKR_USER_TYPE_INVALID; } }
void gkm_module_add_token_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object) { g_return_if_fail (GKM_IS_MODULE (self)); g_return_if_fail (GKM_IS_OBJECT (object)); g_assert (GKM_MODULE_GET_CLASS (self)->add_token_object); if (gkm_object_is_transient (object)) { if (g_hash_table_lookup (self->pv->transient_objects, object) == NULL) add_transient_object (self, transaction, object); } else { GKM_MODULE_GET_CLASS (self)->add_token_object (self, transaction, object); } }
GkmSession* gkm_module_lookup_session (GkmModule *self, CK_SESSION_HANDLE handle) { GkmSession *session; g_return_val_if_fail (GKM_IS_MODULE (self), NULL); session = g_hash_table_lookup (self->pv->sessions_by_handle, &handle); if (!session) return NULL; g_return_val_if_fail (GKM_IS_SESSION (session), NULL); return session; }
GkmMate2Storage* gkm_mate2_storage_new (GkmModule *module, const gchar *directory) { GkmManager *manager; g_return_val_if_fail (GKM_IS_MODULE (module), NULL); g_return_val_if_fail (directory, NULL); manager = gkm_module_get_manager (module); g_return_val_if_fail (GKM_IS_MANAGER (manager), NULL); return g_object_new (GKM_TYPE_MATE2_STORAGE, "module", module, "manager", manager, "directory", directory, NULL); }
static void add_transient_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object) { g_assert (GKM_IS_MODULE (self)); g_assert (GKM_IS_OBJECT (object)); /* Must not already be associated with a session or manager */ g_return_if_fail (gkm_object_get_manager (object) == self->pv->token_manager); g_return_if_fail (g_hash_table_lookup (self->pv->transient_objects, object) == NULL); g_hash_table_insert (self->pv->transient_objects, object, g_object_ref (object)); g_object_set (object, "store", self->pv->transient_store, NULL); gkm_object_expose (object, TRUE); if (transaction) { gkm_transaction_add (transaction, self, (GkmTransactionFunc)complete_transient_add, g_object_ref (object)); } }