static gboolean gcr_secret_exchange_default_derive_transport_key (GcrSecretExchange *exchange, const guchar *peer, gsize n_peer) { GcrSecretExchangeDefault *data = exchange->pv->default_exchange; gpointer ikm; gsize n_ikm; gcry_mpi_t mpi; g_return_val_if_fail (data != NULL, FALSE); g_return_val_if_fail (data->priv != NULL, FALSE); mpi = mpi_from_data (peer, n_peer); if (mpi == NULL) return FALSE; /* Build up a key we can use */ ikm = egg_dh_gen_secret (mpi, data->priv, data->prime, &n_ikm); g_return_val_if_fail (ikm != NULL, FALSE); if (data->key == NULL) data->key = egg_secure_alloc (EXCHANGE_1_KEY_LENGTH); if (!egg_hkdf_perform (EXCHANGE_1_HASH_ALGO, ikm, n_ikm, NULL, 0, NULL, 0, data->key, EXCHANGE_1_KEY_LENGTH)) g_return_val_if_reached (FALSE); egg_secure_free (ikm); gcry_mpi_release (mpi); return TRUE; }
/** * Negotiates crypto between the calling programm and the prompt * * Reads data from the transport section of input_data and sends the public key back * in the transport section of the output_data. * * Returns TRUE on success **/ static gboolean negotiate_transport_crypto (void) { gcry_mpi_t base, prime, peer; gcry_mpi_t key, pub, priv; gboolean ret = FALSE; gpointer ikm; gsize n_ikm; g_assert (!the_key); base = prime = peer = NULL; key = pub = priv = NULL; /* The DH stuff coming in from our caller */ if (gku_prompt_util_decode_mpi (input_data, "transport", "prime", &prime) && gku_prompt_util_decode_mpi (input_data, "transport", "base", &base) && gku_prompt_util_decode_mpi (input_data, "transport", "public", &peer)) { /* Generate our own public/priv, and then a key, send it back */ if (egg_dh_gen_pair (prime, base, 0, &pub, &priv)) { gku_prompt_util_encode_mpi (output_data, "transport", "public", pub); /* Build up a key we can use */ ikm = egg_dh_gen_secret (peer, priv, prime, &n_ikm); if (ikm != NULL) { n_the_key = 16; the_key = egg_secure_alloc (n_the_key); if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0, the_key, n_the_key)) g_return_val_if_reached (FALSE); ret = TRUE; } } } gcry_mpi_release (base); gcry_mpi_release (prime); gcry_mpi_release (peer); gcry_mpi_release (key); gcry_mpi_release (pub); gcry_mpi_release (priv); return ret; }
static gboolean response_open_session_aes (SecretSession *session, GVariant *response) { gconstpointer buffer; GVariant *argument; const gchar *sig; gsize n_buffer; gcry_mpi_t peer; gcry_error_t gcry; gpointer ikm; gsize n_ikm; sig = g_variant_get_type_string (response); g_return_val_if_fail (sig != NULL, FALSE); if (!g_str_equal (sig, "(vo)")) { g_warning ("invalid OpenSession() response from daemon with signature: %s", sig); return FALSE; } g_assert (session->path == NULL); g_variant_get (response, "(vo)", &argument, &session->path); buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar)); gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL); g_return_val_if_fail (gcry == 0, FALSE); g_variant_unref (argument); #if 0 g_printerr (" lib publi: "); gcry_mpi_dump (session->publi); g_printerr ("\n lib peer: "); gcry_mpi_dump (peer); g_printerr ("\n"); #endif ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm); gcry_mpi_release (peer); #if 0 g_printerr (" lib ikm: %s\n", egg_hex_encode (ikm, n_ikm)); #endif if (ikm == NULL) { g_warning ("couldn't negotiate a valid AES session key"); g_free (session->path); session->path = NULL; return FALSE; } session->n_key = 16; session->key = egg_secure_alloc (session->n_key); if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0, session->key, session->n_key)) g_return_val_if_reached (FALSE); egg_secure_free (ikm); session->algorithms = ALGORITHMS_AES; return TRUE; }