diff options
author | Stef Walter <stef@memberwebs.com> | 2009-12-12 00:02:04 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2009-12-12 00:02:04 +0000 |
commit | 7475c3447d99ac271966f6bc80ad36bfcb234474 (patch) | |
tree | 1418930fbaa660215124201d6c1abdafde69fb70 /egg/egg-dh.c | |
parent | d04b105217b1fb5a0a135171abfaa30e6416bbdf (diff) | |
download | gcr-7475c3447d99ac271966f6bc80ad36bfcb234474.tar.gz |
Simplify creation of secret from DH negotiation.
PKCS#11 says to use the low order bytes, and that's what we do
here. This bears more research to make sure we're doing this
in a standard way.
Diffstat (limited to 'egg/egg-dh.c')
-rw-r--r-- | egg/egg-dh.c | 150 |
1 files changed, 59 insertions, 91 deletions
diff --git a/egg/egg-dh.c b/egg/egg-dh.c index d90abc0..f162f4d 100644 --- a/egg/egg-dh.c +++ b/egg/egg-dh.c @@ -21,9 +21,10 @@ #include "config.h" -#include "egg-asn1.h" #include "egg-dh.h" -#include "egg-openssl.h" +#include "egg-secure-memory.h" + +#define DEBUG_DH_SECRET 0 typedef struct _DHGroup { const gchar *name; @@ -238,16 +239,18 @@ egg_dh_default_params (const gchar *name, gcry_mpi_t *prime, gcry_mpi_t *base) gcry_error_t gcry; g_return_val_if_fail (name, FALSE); - g_return_val_if_fail (prime, FALSE); - g_return_val_if_fail (base, FALSE); for (group = dh_groups; group->name; ++group) { if (g_str_equal (group->name, name)) { - gcry = gcry_mpi_scan (prime, GCRYMPI_FMT_USG, group->prime, group->n_prime, NULL); - g_return_val_if_fail (gcry == 0, FALSE); - g_return_val_if_fail (gcry_mpi_get_nbits (*prime) == group->bits, FALSE); - gcry = gcry_mpi_scan (base, GCRYMPI_FMT_USG, group->base, group->n_base, NULL); - g_return_val_if_fail (gcry == 0, FALSE); + if (prime) { + gcry = gcry_mpi_scan (prime, GCRYMPI_FMT_USG, group->prime, group->n_prime, NULL); + g_return_val_if_fail (gcry == 0, FALSE); + g_return_val_if_fail (gcry_mpi_get_nbits (*prime) == group->bits, FALSE); + } + if (base) { + gcry = gcry_mpi_scan (base, GCRYMPI_FMT_USG, group->base, group->n_base, NULL); + g_return_val_if_fail (gcry == 0, FALSE); + } return TRUE; } } @@ -300,91 +303,56 @@ egg_dh_gen_pair (gcry_mpi_t p, gcry_mpi_t g, guint bits, return TRUE; } -gboolean -egg_dh_gen_secret (gcry_mpi_t Y, gcry_mpi_t x, - gcry_mpi_t p, gcry_mpi_t *k) -{ - gint bits; - - g_return_val_if_fail (Y, FALSE); - g_return_val_if_fail (x, FALSE); - g_return_val_if_fail (p, FALSE); - g_return_val_if_fail (k, FALSE); - - bits = gcry_mpi_get_nbits (p); - g_return_val_if_fail (bits >= 0, FALSE); - - *k = gcry_mpi_snew (bits); - g_return_val_if_fail (*k, FALSE); - gcry_mpi_powm (*k, Y, x, p); - - return TRUE; -} - -typedef struct _Parameters { - gcry_mpi_t p; - gcry_mpi_t g; -} Parameters; - -#ifndef EGG_DH_NO_ASN1 - -static gboolean -parse_der_pkcs3 (const guchar *data, gsize n_data, Parameters *params) +gpointer +egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv, + gcry_mpi_t prime, gsize bytes) { - ASN1_TYPE asn; - guchar *buf_p, *buf_g; - gsize n_buf_p, n_buf_g; gcry_error_t gcry; + guchar *value; + gsize n_value; + gsize offset = 0; + gcry_mpi_t k; + gint bits; - asn = egg_asn1_decode ("PK.DHParameter", data, n_data); - if (!asn) - return FALSE; - - buf_p = egg_asn1_read_value (asn, "prime", &n_buf_p, (EggAllocator)g_realloc); - buf_g = egg_asn1_read_value (asn, "base", &n_buf_g, (EggAllocator)g_realloc); - g_return_val_if_fail (buf_p && buf_g, FALSE); - gcry = gcry_mpi_scan (¶ms->p, GCRYMPI_FMT_STD, buf_p, n_buf_p, &n_buf_p); - g_return_val_if_fail (gcry == 0, FALSE); - gcry = gcry_mpi_scan (¶ms->g, GCRYMPI_FMT_STD, buf_g, n_buf_g, &n_buf_g); - g_return_val_if_fail (gcry == 0, FALSE); - - g_free (buf_p); - g_free (buf_g); - return TRUE; -} - -static void -parse_openssl_pkcs3 (GQuark type, const guchar *data, gsize n_data, - GHashTable *headers, gpointer user_data) -{ - Parameters *params = user_data; - - /* Only parse the first one */ - if (params->p != NULL) - return; - - if (g_quark_try_string ("DH PARAMETERS") == type) - parse_der_pkcs3 (data, n_data, params); -} - -gboolean -egg_dh_parse_pkcs3 (const guchar *data, gsize n_data, gcry_mpi_t *p, gcry_mpi_t *g) -{ - Parameters params; - - g_return_val_if_fail (data, FALSE); - g_return_val_if_fail (p, FALSE); - g_return_val_if_fail (g, FALSE); + g_return_val_if_fail (peer, NULL); + g_return_val_if_fail (priv, NULL); + g_return_val_if_fail (prime, NULL); + + bits = gcry_mpi_get_nbits (prime); + g_return_val_if_fail (bits >= 0, NULL); + + k = gcry_mpi_snew (bits); + g_return_val_if_fail (k, NULL); + gcry_mpi_powm (k, peer, priv, prime); + + /* Write out the secret */ + gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n_value, k); + g_return_val_if_fail (gcry == 0, NULL); + if (n_value < bytes) + offset = bytes - n_value; + value = egg_secure_alloc (n_value + offset); + memset (value, 0, n_value + offset); + gcry = gcry_mpi_print (GCRYMPI_FMT_USG, value + offset, n_value, &n_value, k); + g_return_val_if_fail (gcry == 0, NULL); + +#if DEBUG_DH_SECRET + g_printerr ("DH SECRET: "); + gcry_mpi_dump (k); + gcry_mpi_release (k); +#endif + + if (bytes != 0 && bytes < n_value) { + offset = n_value - bytes; + memmove (value, value + offset, bytes); + egg_secure_clear (value + bytes, offset); + } - memset (¶ms, 0, sizeof (params)); - if (!parse_der_pkcs3 (data, n_data, ¶ms)) - egg_openssl_pem_parse (data, n_data, parse_openssl_pkcs3, ¶ms); +#if DEBUG_DH_SECRET + gcry_mpi_scan (&k, GCRYMPI_FMT_USG, value, bytes, NULL); + g_printerr ("RAW SECRET: "); + gcry_mpi_dump (k); + gcry_mpi_release (k); +#endif - if (!params.p || !params.g) - return FALSE; - *p = params.p; - *g = params.g; - return TRUE; + return value; } - -#endif /* EGG_DH_NO_ASN1 */ |