Esempio n. 1
0
static gboolean
perform_encrypt (GcrSecretExchange *self,
                 GKeyFile *output,
                 const gchar *secret,
                 gsize n_secret)
{
	GcrSecretExchangeClass *klass;
	guchar *result, *iv;
	gsize n_result, n_iv;

	klass = GCR_SECRET_EXCHANGE_GET_CLASS (self);
	g_return_val_if_fail (klass->encrypt_transport_data, FALSE);

	if (!(klass->encrypt_transport_data) (self, g_realloc, (const guchar *)secret,
	                                      n_secret, &iv, &n_iv, &result, &n_result))
		return FALSE;

	key_file_set_base64 (output, GCR_SECRET_EXCHANGE_PROTOCOL_1, "secret", result, n_result);
	key_file_set_base64 (output, GCR_SECRET_EXCHANGE_PROTOCOL_1, "iv", iv, n_iv);

	g_free (result);
	g_free (iv);

	return TRUE;
}
Esempio n. 2
0
static gboolean
derive_key (GcrSecretExchange *self,
            GKeyFile *input)
{
	GcrSecretExchangeClass *klass;
	gboolean ret;
	guchar *peer;
	gsize n_peer;

	klass = GCR_SECRET_EXCHANGE_GET_CLASS (self);
	g_return_val_if_fail (klass->derive_transport_key, FALSE);

	g_debug ("deriving shared transport key");

	peer = key_file_get_base64 (input, GCR_SECRET_EXCHANGE_PROTOCOL_1, "public", &n_peer);
	if (peer == NULL) {
		g_message ("secret-exchange: invalid or missing 'public' argument");
		return FALSE;
	}

	ret = (klass->derive_transport_key) (self, peer, n_peer);
	self->pv->derived = ret;

	g_free (peer);
	return ret;
}
Esempio n. 3
0
/**
 * gcr_secret_exchange_receive:
 * @self: a #GcrSecretExchange object
 * @exchange: the string received
 *
 * Receive a string from the other side of secret exchange. This string will
 * have been created by gcr_secret_exchange_begin() or gcr_secret_exchange_send().
 *
 * After this call completes successfully the value returned from
 * gcr_secret_exchange_get_secret() will have changed.
 *
 * Returns: whether the string was successfully parsed and received
 */
gboolean
gcr_secret_exchange_receive (GcrSecretExchange *self,
                             const gchar *exchange)
{
	GcrSecretExchangeClass *klass;
	gchar *secret = NULL;
	gsize n_secret = 0;
	GKeyFile *input;
	gboolean ret;

	g_return_val_if_fail (GCR_IS_SECRET_EXCHANGE (self), FALSE);
	g_return_val_if_fail (exchange != NULL, FALSE);

	klass = GCR_SECRET_EXCHANGE_GET_CLASS (self);
	g_return_val_if_fail (klass->generate_exchange_key, FALSE);
	g_return_val_if_fail (klass->derive_transport_key, FALSE);

	gchar *string = g_strescape (exchange, "");
	g_debug ("receiving secret exchange: %s", string);
	g_free (string);

	/* Parse the input */
	input = g_key_file_new ();
	if (!g_key_file_load_from_data (input, exchange, strlen (exchange),
	                                G_KEY_FILE_NONE, NULL)) {
		g_key_file_free (input);
		g_message ("couldn't parse secret exchange data");
		return FALSE;
	}

	if (!self->pv->generated) {
		if (!(klass->generate_exchange_key) (self, GCR_SECRET_EXCHANGE_PROTOCOL_1,
		                                     &self->pv->publi, &self->pv->n_publi))
			g_return_val_if_reached (FALSE);
		self->pv->generated = TRUE;
	}

	ret = TRUE;

	if (!self->pv->derived) {
		if (!derive_key (self, input))
			ret = FALSE;
	}

	if (ret && g_key_file_has_key (input, GCR_SECRET_EXCHANGE_PROTOCOL_1, "secret", NULL))
		ret = perform_decrypt (self, input, (guchar **)&secret, &n_secret);

	if (ret) {
		egg_secure_free (self->pv->secret);
		self->pv->secret = secret;
		self->pv->n_secret = n_secret;
	}

	g_key_file_free (input);
	return ret;
}
Esempio n. 4
0
static gboolean
perform_decrypt (GcrSecretExchange *self,
                 GKeyFile *input,
                 guchar **secret,
                 gsize *n_secret)
{
	GcrSecretExchangeClass *klass;
	gpointer iv, value;
	guchar *result;
	gsize n_result, n_iv, n_value;
	gboolean ret;

	klass = GCR_SECRET_EXCHANGE_GET_CLASS (self);
	g_return_val_if_fail (klass->decrypt_transport_data, FALSE);

	iv = key_file_get_base64 (input, GCR_SECRET_EXCHANGE_PROTOCOL_1, "iv", &n_iv);

	value = key_file_get_base64 (input, GCR_SECRET_EXCHANGE_PROTOCOL_1, "secret", &n_value);
	if (value == NULL) {
		g_message ("secret-exchange: invalid or missing value");
		g_free (iv);
		return FALSE;
	}

	ret = (klass->decrypt_transport_data) (self, egg_secure_realloc, value, n_value,
	                                       iv, n_iv, &result, &n_result);

	g_free (value);
	g_free (iv);

	if (!ret)
		return FALSE;

	/* Reallocate a null terminator */
	if (result) {
		result = egg_secure_realloc (result, n_result + 1);
		result[n_result] = 0;
	}

	*secret = result;
	*n_secret = n_result;

	return TRUE;
}
Esempio n. 5
0
/**
 * gcr_secret_exchange_begin:
 * @self: a #GcrSecretExchange object
 *
 * Begin the secret exchange. The resulting string should be sent to the other
 * side of the exchange. The other side should use gcr_secret_exchange_receive()
 * to process the string.
 *
 * Returns: (transfer full): A newly allocated string to be sent to the other
 *     side of the secret exchange
 */
gchar *
gcr_secret_exchange_begin (GcrSecretExchange *self)
{
	GcrSecretExchangeClass *klass;
	GKeyFile *output;
	gchar *result;

	g_return_val_if_fail (GCR_IS_SECRET_EXCHANGE (self), NULL);

	klass = GCR_SECRET_EXCHANGE_GET_CLASS (self);
	g_return_val_if_fail (klass->generate_exchange_key, NULL);

	clear_secret_exchange (self);

	output = g_key_file_new ();

	if (!(klass->generate_exchange_key) (self, GCR_SECRET_EXCHANGE_PROTOCOL_1,
	                                     &self->pv->publi, &self->pv->n_publi))
		g_return_val_if_reached (NULL);
	self->pv->generated = TRUE;

	key_file_set_base64 (output, GCR_SECRET_EXCHANGE_PROTOCOL_1, "public",
	                     self->pv->publi, self->pv->n_publi);

	result = g_key_file_to_data (output, NULL, NULL);
	g_return_val_if_fail (result != NULL, NULL);

	g_strchug (result);

	gchar *string = g_strescape (result, "");
	g_debug ("beginning the secret exchange: %s", string);
	g_free (string);

	if (!g_str_has_prefix (result, SECRET_EXCHANGE_PROTOCOL_1_PREFIX))
		g_warning ("the prepared data does not have the correct protocol prefix");

	g_key_file_free (output);

	return result;
}