CK_RV gkm_crypto_wrap_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *wrapper, GkmObject *wrapped, CK_BYTE_PTR output, CK_ULONG_PTR n_output) { g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR); g_return_val_if_fail (GKM_IS_OBJECT (wrapper), CKR_GENERAL_ERROR); g_return_val_if_fail (GKM_IS_OBJECT (wrapped), CKR_GENERAL_ERROR); g_return_val_if_fail (mech, CKR_GENERAL_ERROR); g_return_val_if_fail (n_output, CKR_GENERAL_ERROR); if (!gkm_object_has_attribute_ulong (wrapper, session, CKA_ALLOWED_MECHANISMS, mech->mechanism)) return CKR_KEY_TYPE_INCONSISTENT; if (!gkm_object_has_attribute_boolean (wrapper, session, CKA_WRAP, TRUE)) return CKR_KEY_FUNCTION_NOT_PERMITTED; switch (mech->mechanism) { case CKM_AES_CBC_PAD: return gkm_aes_mechanism_wrap (session, mech, wrapper, wrapped, output, n_output); case CKM_G_NULL: return gkm_null_mechanism_wrap (session, mech, wrapper, wrapped, output, n_output); default: return CKR_MECHANISM_INVALID; } }
void gkm_object_destroy (GkmObject *self, GkmTransaction *transaction) { GkmSession *session; GkmManager *manager; GkmModule *module; g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (self->pv->module); g_object_ref (self); session = gkm_session_for_session_object (self); if (session != NULL) { gkm_session_destroy_session_object (session, transaction, self); } else { manager = gkm_object_get_manager (self); module = gkm_object_get_module (self); if (manager == gkm_module_get_manager (module)) gkm_module_remove_token_object (module, transaction, self); } /* Forcefully dispose of the object once the transaction completes */ gkm_transaction_add (transaction, NULL, complete_destroy, g_object_ref (self)); g_object_unref (self); }
void* gkm_object_get_attribute_data (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_TYPE type, gsize *n_data) { CK_ATTRIBUTE attr; g_return_val_if_fail (GKM_IS_OBJECT (self), NULL); g_return_val_if_fail (n_data, NULL); attr.type = type; attr.ulValueLen = 0; attr.pValue = NULL; if (gkm_object_get_attribute (self, session, &attr) != CKR_OK) return NULL; if (attr.ulValueLen == 0) attr.ulValueLen = 1; attr.pValue = g_malloc0 (attr.ulValueLen); if (gkm_object_get_attribute (self, session, &attr) != CKR_OK) { g_free (attr.pValue); return NULL; } *n_data = attr.ulValueLen; return attr.pValue; }
CK_RV gkm_crypto_derive_key (GkmSession *session, CK_MECHANISM_PTR mech, GkmObject *base, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, GkmObject **derived) { g_return_val_if_fail (GKM_IS_SESSION (session), CKR_GENERAL_ERROR); g_return_val_if_fail (GKM_IS_OBJECT (base), CKR_GENERAL_ERROR); g_return_val_if_fail (derived, CKR_GENERAL_ERROR); if (!gkm_object_has_attribute_ulong (base, session, CKA_ALLOWED_MECHANISMS, mech->mechanism)) return CKR_KEY_TYPE_INCONSISTENT; if (!gkm_object_has_attribute_boolean (base, session, CKA_DERIVE, TRUE)) return CKR_KEY_FUNCTION_NOT_PERMITTED; switch (mech->mechanism) { case CKM_DH_PKCS_DERIVE: return gkm_dh_mechanism_derive (session, mech, base, attrs, n_attrs, derived); case CKM_G_HKDF_SHA256_DERIVE: return gkm_hkdf_mechanism_derive (session, "sha256", mech, base, attrs, n_attrs, derived); default: return CKR_MECHANISM_INVALID; } }
CK_RV gkm_object_unlock (GkmObject *self, GkmCredential *cred) { g_return_val_if_fail (GKM_IS_OBJECT (self), CKR_GENERAL_ERROR); g_return_val_if_fail (GKM_OBJECT_GET_CLASS (self)->unlock, CKR_GENERAL_ERROR); return GKM_OBJECT_GET_CLASS (self)->unlock (self, cred); }
gboolean gkm_object_match (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_PTR match) { CK_ATTRIBUTE attr; gboolean matched = FALSE; CK_RV rv; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); if (!match->pValue) return FALSE; attr.type = match->type; attr.pValue = g_malloc0 (match->ulValueLen > 4 ? match->ulValueLen : 4); attr.ulValueLen = match->ulValueLen; matched = FALSE; rv = gkm_object_get_attribute (self, session, &attr); matched = (rv == CKR_OK) && (match->ulValueLen == attr.ulValueLen) && (memcmp (match->pValue, attr.pValue, attr.ulValueLen) == 0); g_free (attr.pValue); return matched; }
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; }
gboolean gkm_object_has_attribute_ulong (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_TYPE type, gulong value) { gulong *data; gsize n_data, i; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); g_return_val_if_fail (GKM_IS_SESSION (session), FALSE); data = gkm_object_get_attribute_data (self, session, type, &n_data); if (data == NULL) return FALSE; g_return_val_if_fail (n_data % sizeof (gulong) == 0, FALSE); for (i = 0; i < n_data / sizeof (gulong); ++i) { if (data[i] == value) { g_free (data); return TRUE; } } g_free (data); return FALSE; }
gboolean gkm_object_is_token (GkmObject *self) { g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); if (!self->pv->manager) return FALSE; return gkm_manager_get_for_token (self->pv->manager); }
CK_RV gkm_object_get_attribute (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_PTR attr) { g_return_val_if_fail (GKM_IS_OBJECT (self), CKR_GENERAL_ERROR); g_return_val_if_fail (attr, CKR_GENERAL_ERROR); g_assert (GKM_OBJECT_GET_CLASS (self)->get_attribute); return GKM_OBJECT_GET_CLASS (self)->get_attribute (self, session, attr); }
void gkm_object_set_handle (GkmObject *self, CK_OBJECT_HANDLE handle) { g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (handle != 0); g_return_if_fail (self->pv->handle == 0); self->pv->handle = handle; g_object_notify (G_OBJECT (self), "handle"); }
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); }
void gkm_credential_connect (GkmCredential *self, GkmObject *object) { g_return_if_fail (GKM_IS_CREDENTIAL (self)); g_return_if_fail (GKM_IS_OBJECT (object)); g_return_if_fail (self->pv->object == NULL); g_return_if_fail (GKM_OBJECT (self) != object); self->pv->object = object; g_object_weak_ref (G_OBJECT (self->pv->object), object_went_away, self); }
void gkm_object_expose (GkmObject *self, gboolean expose) { if (!expose && !self) return; g_return_if_fail (GKM_IS_OBJECT (self)); if (self->pv->exposed != expose) g_signal_emit (self, signals[EXPOSE_OBJECT], 0, expose); }
gboolean gkm_object_has_attribute_boolean (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_TYPE type, gboolean value) { gboolean data; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); g_return_val_if_fail (GKM_IS_SESSION (session), FALSE); if (!gkm_object_get_attribute_boolean (self, session, type, &data)) return FALSE; return data == value; }
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); } }
static void gkm_mate2_storage_real_write_value (GkmStore *base, GkmTransaction *transaction, GkmObject *object, CK_ATTRIBUTE_PTR attr) { GkmMate2Storage *self = GKM_MATE2_STORAGE (base); const gchar *identifier; GkmDataResult res; CK_RV rv; g_return_if_fail (GKM_IS_MATE2_STORAGE (self)); g_return_if_fail (GKM_IS_OBJECT (object)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (attr); identifier = g_hash_table_lookup (self->object_to_identifier, object); if (!identifier) { gkm_transaction_fail (transaction, CKR_ATTRIBUTE_READ_ONLY); return; } if (self->last_mtime == 0) { rv = gkm_mate2_storage_refresh (self); if (rv != CKR_OK) { gkm_transaction_fail (transaction, rv); return; } } res = gkm_mate2_file_write_value (self->file, identifier, attr->type, attr->pValue, attr->ulValueLen); switch (res) { case GKM_DATA_FAILURE: rv = CKR_FUNCTION_FAILED; break; case GKM_DATA_UNRECOGNIZED: rv = CKR_ATTRIBUTE_READ_ONLY; break; case GKM_DATA_LOCKED: rv = CKR_USER_NOT_LOGGED_IN; break; case GKM_DATA_SUCCESS: rv = CKR_OK; break; default: g_assert_not_reached (); } if (rv != CKR_OK) gkm_transaction_fail (transaction, rv); }
void gkm_object_set_attribute (GkmObject *self, GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attr) { g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (attr); g_assert (GKM_OBJECT_GET_CLASS (self)->set_attribute); /* Check that the value will actually change */ if (!gkm_object_match (self, session, attr)) GKM_OBJECT_GET_CLASS (self)->set_attribute (self, session, transaction, attr); }
gboolean gkm_object_match_all (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { CK_ULONG i; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); for (i = 0; i < n_attrs; ++i) { if (!gkm_object_match (self, session, &attrs[i])) return FALSE; } return TRUE; }
void gkm_object_create_attributes (GkmObject *self, GkmSession *session, GkmTransaction *transaction, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs) { g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (GKM_IS_TRANSACTION (transaction)); g_return_if_fail (!gkm_transaction_get_failed (transaction)); g_return_if_fail (GKM_IS_SESSION (session)); g_return_if_fail (attrs); g_assert (GKM_OBJECT_GET_CLASS (self)->create_attributes); /* Check that the value will actually change */ GKM_OBJECT_GET_CLASS (self)->create_attributes (self, session, transaction, attrs, n_attrs); }
void gkm_object_expose_full (GkmObject *self, GkmTransaction *transaction, gboolean expose) { if (!expose && !self) return; g_return_if_fail (GKM_IS_OBJECT (self)); g_return_if_fail (!transaction || !gkm_transaction_get_failed (transaction)); if (self->pv->exposed != expose) { if (transaction) gkm_transaction_add (transaction, self, complete_expose, GUINT_TO_POINTER (expose)); gkm_object_expose (self, expose); } }
static void timer_callback (GkmTimer *timer, gpointer user_data) { GkmObject *self = user_data; glong after, idle, offset; GkmObjectTransient *transient; GTimeVal tv; g_return_if_fail (GKM_IS_OBJECT (self)); g_object_ref (self); g_return_if_fail (self->pv->transient); transient = self->pv->transient; g_return_if_fail (timer == transient->timer); transient->timer = NULL; g_get_current_time (&tv); idle = after = G_MAXLONG; /* Are we supposed to be destroyed after a certain time? */ if (transient->timed_after) { g_return_if_fail (transient->stamp_created); after = (transient->stamp_created + transient->timed_after) - tv.tv_sec; } /* Are we supposed to be destroyed after an idle time? */ if (transient->timed_idle) { g_return_if_fail (transient->stamp_used); idle = (transient->stamp_used + transient->timed_idle) - tv.tv_sec; } /* Okay, time to destroy? */ offset = MIN (after, idle); if (offset <= 0) self_destruct (self); /* Setup the next timer */ else transient->timer = gkm_timer_start (self->pv->module, offset, timer_callback, self); g_object_unref (self); }
static void take_object_ownership (GkmMate2Storage *self, const gchar *identifier, GkmObject *object) { gchar *str; g_assert (GKM_IS_MATE2_STORAGE (self)); g_assert (GKM_IS_OBJECT (object)); g_assert (g_hash_table_lookup (self->identifier_to_object, identifier) == NULL); g_assert (g_hash_table_lookup (self->object_to_identifier, object) == NULL); str = g_strdup (identifier); object = g_object_ref (object); g_hash_table_replace (self->identifier_to_object, str, object); g_hash_table_replace (self->object_to_identifier, object, str);; g_object_set (object, "store", self, NULL); gkm_object_expose (object, TRUE); }
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)); } }
gboolean gkm_object_get_attribute_boolean (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_TYPE type, gboolean *value) { CK_ATTRIBUTE attr; CK_BBOOL bvalue; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); g_return_val_if_fail (value, FALSE); attr.type = type; attr.ulValueLen = sizeof (CK_BBOOL); attr.pValue = &bvalue; if (gkm_object_get_attribute (self, session, &attr) != CKR_OK) return FALSE; *value = (bvalue == CK_TRUE) ? TRUE : FALSE; return TRUE; }
gboolean gkm_object_get_attribute_ulong (GkmObject *self, GkmSession *session, CK_ATTRIBUTE_TYPE type, gulong *value) { CK_ATTRIBUTE attr; CK_ULONG uvalue; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); g_return_val_if_fail (value, FALSE); attr.type = type; attr.ulValueLen = sizeof (CK_ULONG); attr.pValue = &uvalue; if (gkm_object_get_attribute (self, session, &attr) != CKR_OK) return FALSE; *value = uvalue; return TRUE; }
static gboolean start_callback (GkmTransaction *transaction, GObject *obj, gpointer user_data) { GkmObject *self = GKM_OBJECT (obj); GkmObjectTransient *transient; GTimeVal tv; g_return_val_if_fail (GKM_IS_OBJECT (self), FALSE); g_return_val_if_fail (self->pv->transient, FALSE); transient = self->pv->transient; g_return_val_if_fail (!transient->timer, FALSE); g_get_current_time (&tv); transient->stamp_created = tv.tv_sec; transient->stamp_used = tv.tv_sec; /* Start the timer going */ timer_callback (NULL, self); return TRUE; }
static CK_RV gkm_mate2_storage_real_read_value (GkmStore *base, GkmObject *object, CK_ATTRIBUTE_PTR attr) { GkmMate2Storage *self = GKM_MATE2_STORAGE (base); const gchar *identifier; GkmDataResult res; gconstpointer value; gsize n_value; CK_RV rv; g_return_val_if_fail (GKM_IS_MATE2_STORAGE (self), CKR_GENERAL_ERROR); g_return_val_if_fail (GKM_IS_OBJECT (object), CKR_GENERAL_ERROR); g_return_val_if_fail (attr, CKR_GENERAL_ERROR); identifier = g_hash_table_lookup (self->object_to_identifier, object); if (!identifier) return CKR_ATTRIBUTE_TYPE_INVALID; if (self->last_mtime == 0) { rv = gkm_mate2_storage_refresh (self); if (rv != CKR_OK) return rv; } res = gkm_mate2_file_read_value (self->file, identifier, attr->type, &value, &n_value); switch (res) { case GKM_DATA_FAILURE: g_return_val_if_reached (CKR_GENERAL_ERROR); case GKM_DATA_UNRECOGNIZED: return CKR_ATTRIBUTE_TYPE_INVALID; case GKM_DATA_LOCKED: return CKR_USER_NOT_LOGGED_IN; case GKM_DATA_SUCCESS: /* Yes, we don't fill a buffer, just return pointer */ attr->pValue = (CK_VOID_PTR)value; attr->ulValueLen = n_value; return CKR_OK; default: g_assert_not_reached (); } }
static void remove_transient_object (GkmModule *self, GkmTransaction *transaction, GkmObject *object) { g_assert (GKM_IS_MODULE (self)); g_assert (GKM_IS_OBJECT (object)); g_object_ref (object); gkm_object_expose (object, FALSE); if (!g_hash_table_remove (self->pv->transient_objects, object)) g_return_if_reached (); g_object_set (object, "store", NULL, NULL); if (transaction) { gkm_transaction_add (transaction, self, (GkmTransactionFunc)complete_transient_remove, g_object_ref (object)); } g_object_unref (object); }
void gkm_object_mark_used (GkmObject *self) { GkmObjectTransient *transient; GTimeVal tv; g_return_if_fail (GKM_IS_OBJECT (self)); transient = self->pv->transient; if (transient) { if (transient->timed_idle) { g_get_current_time (&tv); transient->stamp_used = tv.tv_sec; } if (transient->uses_remaining) { --(transient->uses_remaining); if (transient->uses_remaining == 0) self_destruct (self); } } }