diff options
Diffstat (limited to 'src/libstrongswan/crypto/diffie_hellman.c')
-rw-r--r-- | src/libstrongswan/crypto/diffie_hellman.c | 293 |
1 files changed, 135 insertions, 158 deletions
diff --git a/src/libstrongswan/crypto/diffie_hellman.c b/src/libstrongswan/crypto/diffie_hellman.c index e4062066c..605892e87 100644 --- a/src/libstrongswan/crypto/diffie_hellman.c +++ b/src/libstrongswan/crypto/diffie_hellman.c @@ -8,7 +8,7 @@ /* * Copyright (C) 1998-2002 D. Hugh Redelmeier. * Copyright (C) 1999, 2000, 2001 Henry Spencer. - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -24,11 +24,11 @@ */ #include <gmp.h> -#include <stdio.h> #include "diffie_hellman.h" #include <utils/randomizer.h> +#include <debug.h> ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT, "MODP_NONE", @@ -302,12 +302,12 @@ static u_int8_t group18_modulus[] = { 0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; -typedef struct modulus_info_entry_t modulus_info_entry_t; +typedef struct modulus_entry_t modulus_entry_t; /** * Entry of the modulus list. */ -struct modulus_info_entry_t { +struct modulus_entry_t { /** * Group number as it is defined in file transform_substructure.h. */ @@ -321,7 +321,7 @@ struct modulus_info_entry_t { /* * Length of modulus in bytes. */ - size_t modulus_length; + size_t modulus_len; /* * Generator value. @@ -329,19 +329,18 @@ struct modulus_info_entry_t { u_int16_t generator; }; - /** * All supported modulus values. */ -static modulus_info_entry_t modulus_info_entries[] = { - {MODP_768_BIT,group1_modulus,sizeof(group1_modulus),2}, - {MODP_1024_BIT,group2_modulus,sizeof(group2_modulus),2}, - {MODP_1536_BIT,group5_modulus,sizeof(group5_modulus),2}, - {MODP_2048_BIT,group14_modulus,sizeof(group14_modulus),2}, - {MODP_3072_BIT,group15_modulus,sizeof(group15_modulus),2}, - {MODP_4096_BIT,group16_modulus,sizeof(group16_modulus),2}, - {MODP_6144_BIT,group17_modulus,sizeof(group17_modulus),2}, - {MODP_8192_BIT,group18_modulus,sizeof(group18_modulus),2}, +static modulus_entry_t modulus_entries[] = { + {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 2}, + {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 2}, + {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 2}, + {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 2}, + {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 2}, + {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 2}, + {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 2}, + {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 2}, }; typedef struct private_diffie_hellman_t private_diffie_hellman_t; @@ -359,170 +358,133 @@ struct private_diffie_hellman_t { /** * Diffie Hellman group number. */ - u_int16_t dh_group_number; - - /** - * Modulus. - */ - mpz_t modulus; - - /** - * Modulus length. - */ - size_t modulus_length; + u_int16_t group; /* * Generator value. */ - u_int16_t generator; + mpz_t g; /** - * My private value . + * My private value. */ - mpz_t my_private_value; + mpz_t xa; /** * My public value. */ - mpz_t my_public_value; + mpz_t ya; /** * Other public value. */ - mpz_t other_public_value; + mpz_t yb; /** * Shared secret. */ - mpz_t shared_secret; + mpz_t zz; /** - * True if shared secret is computed and stored in my_public_value. - */ - bool shared_secret_is_computed; - - /** - * Sets the modulus for a specific diffie hellman group. - * - * @param this calling object - * @return - * SUCCESS if modulus could be found - * NOT_FOUND if modulus not supported + * Modulus. */ - status_t (*set_modulus) (private_diffie_hellman_t *this); + mpz_t p; /** - * Makes sure my public value is computed. - * - * @param this calling object + * Modulus length. */ - void (*compute_public_value) (private_diffie_hellman_t *this); + size_t p_len; /** - * Computes shared secret (other public value must be available). - * - * @param this calling object + * True if shared secret is computed and stored in my_public_value. */ - void (*compute_shared_secret) (private_diffie_hellman_t *this); + bool computed; }; /** - * Implementation of private_diffie_hellman_t.set_modulus. + * Implementation of diffie_hellman_t.set_other_public_value. */ -static status_t set_modulus(private_diffie_hellman_t *this) +static void set_other_public_value(private_diffie_hellman_t *this, chunk_t value) { - int i; - status_t status = NOT_FOUND; + mpz_t p_min_1; + + mpz_init(p_min_1); + mpz_sub_ui(p_min_1, this->p, 1); + + mpz_import(this->yb, value.len, 1, 1, 1, 0, value.ptr); - for (i = 0; i < (sizeof(modulus_info_entries) / sizeof(modulus_info_entry_t)); i++) + /* check public value: + * 1. 0 or 1 is invalid as 0^a = 0 and 1^a = 1 + * 2. a public value larger or equal the modulus is invalid */ + if (mpz_cmp_ui(this->yb, 1) > 0 || + mpz_cmp(this->yb, p_min_1) < 0) { - if (modulus_info_entries[i].group == this->dh_group_number) +#ifdef EXTENDED_DH_TEST + /* 3. test if y ^ q mod p = 1, where q = (p - 1)/2. */ + mpz_t q, one; + + mpz_init(q); + mpz_init(one); + mpz_fdiv_q_2exp(q, p_min_1, 1); + mpz_powm(one, this->yb, q, this->p); + mpz_clear(q); + if (mpz_cmp_ui(one, 1) == 0) { - chunk_t modulus_chunk; - modulus_chunk.ptr = modulus_info_entries[i].modulus; - modulus_chunk.len = modulus_info_entries[i].modulus_length; - mpz_import(this->modulus, modulus_chunk.len, 1, 1, 1, 0, modulus_chunk.ptr); - this->modulus_length = modulus_chunk.len; - this->generator = modulus_info_entries[i].generator; - status = SUCCESS; - break; + mpz_powm(this->zz, this->yb, this->xa, this->p); + this->computed = TRUE; + } + else + { + DBG1("public DH value verification failed: y ^ q mod p != 1"); } + mpz_clear(one); +#else + mpz_powm(this->zz, this->yb, this->xa, this->p); + this->computed = TRUE; +#endif } - return status; -} - -/** - * Implementation of diffie_hellman_t.set_other_public_value. - */ -static void set_other_public_value(private_diffie_hellman_t *this,chunk_t public_value) -{ - mpz_import(this->other_public_value, public_value.len, 1, 1, 1, 0, public_value.ptr); - this->compute_shared_secret(this); + else + { + DBG1("public DH value verification failed: y < 2 || y > p - 1 "); + } + mpz_clear(p_min_1); } /** * Implementation of diffie_hellman_t.get_other_public_value. */ -static status_t get_other_public_value(private_diffie_hellman_t *this,chunk_t *public_value) +static status_t get_other_public_value(private_diffie_hellman_t *this, + chunk_t *value) { - if (!this->shared_secret_is_computed) + if (!this->computed) { return FAILED; } - public_value->len = this->modulus_length; - public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->other_public_value); + value->len = this->p_len; + value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->yb); return SUCCESS; } /** - * Implementation of private_diffie_hellman_t.compute_shared_secret. - */ -static void compute_shared_secret (private_diffie_hellman_t *this) -{ - /* initialize my public value */ - mpz_init(this->shared_secret); - /* calculate my public value */ - mpz_powm(this->shared_secret,this->other_public_value,this->my_private_value,this->modulus); - - this->shared_secret_is_computed = TRUE; -} - -/** - * Implementation of private_diffie_hellman_t.compute_public_value. - */ -static void compute_public_value (private_diffie_hellman_t *this) -{ - mpz_t generator; - /* initialize generator and set it*/ - mpz_init_set_ui (generator,this->generator); - /* initialize my public value */ - mpz_init(this->my_public_value); - /* calculate my public value */ - mpz_powm(this->my_public_value,generator,this->my_private_value,this->modulus); - /* generator not used anymore */ - mpz_clear(generator); -} - -/** * Implementation of diffie_hellman_t.get_my_public_value. */ -static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *public_value) +static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *value) { - public_value->len = this->modulus_length; - public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->my_public_value); + value->len = this->p_len; + value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->ya); } /** * Implementation of diffie_hellman_t.get_shared_secret. */ -static status_t get_shared_secret(private_diffie_hellman_t *this,chunk_t *secret) +static status_t get_shared_secret(private_diffie_hellman_t *this, chunk_t *secret) { - if (!this->shared_secret_is_computed) + if (!this->computed) { return FAILED; } - secret->len = this->modulus_length; - secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->shared_secret); + secret->len = this->p_len; + secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->zz); return SUCCESS; } @@ -531,35 +493,57 @@ static status_t get_shared_secret(private_diffie_hellman_t *this,chunk_t *secret */ static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this) { - return this->dh_group_number; + return this->group; } /** - * Implementation of diffie_hellman_t.destroy. + * Lookup the modulus in modulo table */ -static void destroy(private_diffie_hellman_t *this) +static status_t set_modulus(private_diffie_hellman_t *this) { - mpz_clear(this->modulus); - mpz_clear(this->my_private_value); - mpz_clear(this->my_public_value); - mpz_clear(this->other_public_value); - - if (this->shared_secret_is_computed) + int i; + status_t status = NOT_FOUND; + + for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++) { - /* other public value gets initialized together with shared secret */ - mpz_clear(this->shared_secret); + if (modulus_entries[i].group == this->group) + { + chunk_t chunk; + chunk.ptr = modulus_entries[i].modulus; + chunk.len = modulus_entries[i].modulus_len; + mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr); + this->p_len = chunk.len; + mpz_set_ui(this->g, modulus_entries[i].generator); + status = SUCCESS; + break; + } } + return status; +} + +/** + * Implementation of diffie_hellman_t.destroy. + */ +static void destroy(private_diffie_hellman_t *this) +{ + mpz_clear(this->p); + mpz_clear(this->xa); + mpz_clear(this->ya); + mpz_clear(this->yb); + mpz_clear(this->zz); + mpz_clear(this->g); free(this); } /* * Described in header. */ -diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number) +diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t group) { private_diffie_hellman_t *this = malloc_thing(private_diffie_hellman_t); randomizer_t *randomizer; - chunk_t random_bytes; + chunk_t random; + status_t status; /* public functions */ this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; @@ -569,44 +553,37 @@ diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number) this->public.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; this->public.destroy = (void (*)(diffie_hellman_t *)) destroy; - /* private functions */ - this->set_modulus = set_modulus; - this->compute_public_value = compute_public_value; - this->compute_shared_secret = compute_shared_secret; - /* private variables */ - this->dh_group_number = dh_group_number; - mpz_init(this->modulus); - mpz_init(this->other_public_value); - mpz_init(this->my_private_value); + this->group = group; + mpz_init(this->p); + mpz_init(this->yb); + mpz_init(this->ya); + mpz_init(this->xa); + mpz_init(this->zz); + mpz_init(this->g); + + this->computed = FALSE; - /* set this->modulus */ - if (this->set_modulus(this) != SUCCESS) + /* find a modulus according to group */ + if (set_modulus(this) != SUCCESS) { - free(this); + destroy(this); return NULL; } randomizer = randomizer_create(); - if (randomizer == NULL) - { - free(this); - return NULL; - } - if (randomizer->allocate_pseudo_random_bytes(randomizer, this->modulus_length, &random_bytes) != SUCCESS) + status = randomizer->allocate_pseudo_random_bytes( + randomizer, this->p_len, &random); + randomizer->destroy(randomizer); + if (status != SUCCESS) { - randomizer->destroy(randomizer); - free(this); + destroy(this); return NULL; } + mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr); + chunk_free(&random); - mpz_import(this->my_private_value, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); - chunk_free(&random_bytes); + mpz_powm(this->ya, this->g, this->xa, this->p); - randomizer->destroy(randomizer); - - this->compute_public_value(this); - - this->shared_secret_is_computed = FALSE; - - return &(this->public); + return &this->public; } + |