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; }
/** * gcr_secret_exchange_send: * @self: a #GcrSecretExchange object * @secret: (allow-none): optionally, a secret to send to the other side * @secret_len: length of @secret, or -1 if null terminated * * Send a reply to the other side of the secret exchange, optionally sending a * secret. * * gcr_secret_exchange_receive() must have been successfully called at least * once on this object. In other words this object must have received data * from the other side of the secret exchange, before we can send a secret. * * Returns: (transfer full): a newly allocated string to be sent to the other * side of the secret exchange */ gchar * gcr_secret_exchange_send (GcrSecretExchange *self, const gchar *secret, gssize secret_len) { GKeyFile *output; gchar *result; g_return_val_if_fail (GCR_IS_SECRET_EXCHANGE (self), NULL); if (!self->pv->derived) { g_warning ("gcr_secret_exchange_receive() must be called " "before calling this function"); return NULL; } output = g_key_file_new (); key_file_set_base64 (output, GCR_SECRET_EXCHANGE_PROTOCOL_1, "public", self->pv->publi, self->pv->n_publi); if (secret != NULL) { if (secret_len < 0) secret_len = strlen (secret); if (!perform_encrypt (self, output, secret, secret_len)) { g_key_file_free (output); return NULL; } } 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 ("sending 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: %s", result); g_key_file_free (output); return result; }
/** * 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; }