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;
}
예제 #4
0
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);
}
예제 #13
0
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);
	}
}
예제 #17
0
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);
}
예제 #23
0
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;
}
예제 #28
0
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);
		}
	}
}