implemented an optional DH public value test

some other cleanups, using RFC2631 variable names
This commit is contained in:
Martin Willi
2007-10-04 15:19:24 +00:00
parent 40f10fd88e
commit c96aefe268
2 changed files with 129 additions and 129 deletions
+96 -93
View File
@@ -8,7 +8,7 @@
/* /*
* Copyright (C) 1998-2002 D. Hugh Redelmeier. * Copyright (C) 1998-2002 D. Hugh Redelmeier.
* Copyright (C) 1999, 2000, 2001 Henry Spencer. * Copyright (C) 1999, 2000, 2001 Henry Spencer.
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@@ -24,7 +24,6 @@
*/ */
#include <gmp.h> #include <gmp.h>
#include <stdio.h>
#include "diffie_hellman.h" #include "diffie_hellman.h"
@@ -322,7 +321,7 @@ struct modulus_entry_t {
/* /*
* Length of modulus in bytes. * Length of modulus in bytes.
*/ */
size_t modulus_length; size_t modulus_len;
/* /*
* Generator value. * Generator value.
@@ -359,42 +358,42 @@ struct private_diffie_hellman_t {
/** /**
* Diffie Hellman group number. * Diffie Hellman group number.
*/ */
u_int16_t dh_group_number; u_int16_t group;
/**
* Modulus.
*/
mpz_t modulus;
/**
* Modulus length.
*/
size_t modulus_length;
/* /*
* Generator value. * Generator value.
*/ */
u_int16_t generator; mpz_t g;
/** /**
* My private value . * My private value.
*/ */
mpz_t private; mpz_t xa;
/** /**
* My public value. * My public value.
*/ */
mpz_t my_public; mpz_t ya;
/** /**
* Other public value. * Other public value.
*/ */
mpz_t other_public; mpz_t yb;
/** /**
* Shared secret. * Shared secret.
*/ */
mpz_t secret; mpz_t zz;
/**
* Modulus.
*/
mpz_t p;
/**
* Modulus length.
*/
size_t p_len;
/** /**
* True if shared secret is computed and stored in my_public_value. * True if shared secret is computed and stored in my_public_value.
@@ -402,32 +401,53 @@ struct private_diffie_hellman_t {
bool computed; bool computed;
}; };
/**
* Compute the shared secret
*/
static void compute_shared_secret(private_diffie_hellman_t *this)
{
mpz_powm(this->secret, this->other_public, this->private, this->modulus);
this->computed = TRUE;
}
/** /**
* Implementation of diffie_hellman_t.set_other_public_value. * Implementation of diffie_hellman_t.set_other_public_value.
*/ */
static void set_other_public_value(private_diffie_hellman_t *this, chunk_t value) static void set_other_public_value(private_diffie_hellman_t *this, chunk_t value)
{ {
mpz_import(this->other_public, value.len, 1, 1, 1, 0, value.ptr); mpz_t p_min_1;
/* check public value: */ mpz_init(p_min_1);
/* 1. 0 or 1 wouldn't include your generated value */ mpz_sub_ui(p_min_1, this->p, 1);
/* 2. a public value larger or equal the modulus is invalid anyway */
if (mpz_cmp_ui(this->other_public, 1) <= 0 || mpz_import(this->yb, value.len, 1, 1, 1, 0, value.ptr);
mpz_cmp(this->other_public, this->modulus) >= 0)
/* 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)
{ {
DBG1("public DH value verification failed: 0/1"); #ifdef EXTENDED_DH_TEST
return; /* 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)
{
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
} }
compute_shared_secret(this); else
{
DBG1("public DH value verification failed: y < 2 || y > p - 1 ");
}
mpz_clear(p_min_1);
} }
/** /**
@@ -440,32 +460,18 @@ static status_t get_other_public_value(private_diffie_hellman_t *this,
{ {
return FAILED; return FAILED;
} }
value->len = this->modulus_length; value->len = this->p_len;
value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->other_public); value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->yb);
return SUCCESS; return SUCCESS;
} }
/**
* Implementation of private_diffie_hellman_t.compute_public_value.
*/
static void compute_public_value(private_diffie_hellman_t *this)
{
mpz_t generator;
mpz_init_set_ui(generator, this->generator);
mpz_powm(this->my_public, generator, this->private, this->modulus);
mpz_clear(generator);
}
/** /**
* Implementation of diffie_hellman_t.get_my_public_value. * Implementation of diffie_hellman_t.get_my_public_value.
*/ */
static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *value) static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *value)
{ {
value->len = this->modulus_length; value->len = this->p_len;
value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->my_public); value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->ya);
} }
/** /**
@@ -477,8 +483,8 @@ static status_t get_shared_secret(private_diffie_hellman_t *this, chunk_t *secre
{ {
return FAILED; return FAILED;
} }
secret->len = this->modulus_length; secret->len = this->p_len;
secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->secret); secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->zz);
return SUCCESS; return SUCCESS;
} }
@@ -487,7 +493,7 @@ static status_t get_shared_secret(private_diffie_hellman_t *this, chunk_t *secre
*/ */
static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this) static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this)
{ {
return this->dh_group_number; return this->group;
} }
/** /**
@@ -500,14 +506,14 @@ static status_t set_modulus(private_diffie_hellman_t *this)
for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++) for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++)
{ {
if (modulus_entries[i].group == this->dh_group_number) if (modulus_entries[i].group == this->group)
{ {
chunk_t chunk; chunk_t chunk;
chunk.ptr = modulus_entries[i].modulus; chunk.ptr = modulus_entries[i].modulus;
chunk.len = modulus_entries[i].modulus_length; chunk.len = modulus_entries[i].modulus_len;
mpz_import(this->modulus, chunk.len, 1, 1, 1, 0, chunk.ptr); mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr);
this->modulus_length = chunk.len; this->p_len = chunk.len;
this->generator = modulus_entries[i].generator; mpz_set_ui(this->g, modulus_entries[i].generator);
status = SUCCESS; status = SUCCESS;
break; break;
} }
@@ -520,22 +526,23 @@ static status_t set_modulus(private_diffie_hellman_t *this)
*/ */
static void destroy(private_diffie_hellman_t *this) static void destroy(private_diffie_hellman_t *this)
{ {
mpz_clear(this->modulus); mpz_clear(this->p);
mpz_clear(this->private); mpz_clear(this->xa);
mpz_clear(this->my_public); mpz_clear(this->ya);
mpz_clear(this->other_public); mpz_clear(this->yb);
mpz_clear(this->secret); mpz_clear(this->zz);
free(this); free(this);
} }
/* /*
* Described in header. * 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); private_diffie_hellman_t *this = malloc_thing(private_diffie_hellman_t);
randomizer_t *randomizer; randomizer_t *randomizer;
chunk_t random; chunk_t random;
status_t status;
/* public functions */ /* public functions */
this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
@@ -546,39 +553,35 @@ diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number)
this->public.destroy = (void (*)(diffie_hellman_t *)) destroy; this->public.destroy = (void (*)(diffie_hellman_t *)) destroy;
/* private variables */ /* private variables */
this->dh_group_number = dh_group_number; this->group = group;
mpz_init(this->modulus); mpz_init(this->p);
mpz_init(this->other_public); mpz_init(this->yb);
mpz_init(this->my_public); mpz_init(this->ya);
mpz_init(this->private); mpz_init(this->xa);
mpz_init(this->secret); mpz_init(this->zz);
mpz_init(this->g);
this->computed = FALSE; this->computed = FALSE;
/* set this->modulus */ /* find a modulus according to group */
if (set_modulus(this) != SUCCESS) if (set_modulus(this) != SUCCESS)
{ {
destroy(this); destroy(this);
return NULL; return NULL;
} }
randomizer = randomizer_create(); randomizer = randomizer_create();
if (randomizer == NULL) status = randomizer->allocate_pseudo_random_bytes(
{ randomizer, this->p_len, &random);
destroy(this);
return NULL;
}
if (randomizer->allocate_pseudo_random_bytes(randomizer,
this->modulus_length, &random) != SUCCESS)
{
randomizer->destroy(randomizer);
destroy(this);
return NULL;
}
mpz_import(this->private, random.len, 1, 1, 1, 0, random.ptr);
chunk_free(&random);
randomizer->destroy(randomizer); randomizer->destroy(randomizer);
if (status != SUCCESS)
{
destroy(this);
return NULL;
}
mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr);
chunk_free(&random);
compute_public_value(this); mpz_powm(this->ya, this->g, this->xa, this->p);
return &this->public; return &this->public;
} }
+33 -36
View File
@@ -6,7 +6,7 @@
*/ */
/* /*
* Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter * Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@@ -36,7 +36,7 @@ typedef struct diffie_hellman_t diffie_hellman_t;
* *
* See IKEv2 RFC 3.3.2 and RFC 3526. * See IKEv2 RFC 3.3.2 and RFC 3526.
* *
* @ingroup transforms * @ingroup crypto
*/ */
enum diffie_hellman_group_t { enum diffie_hellman_group_t {
MODP_NONE = 0, MODP_NONE = 0,
@@ -56,76 +56,74 @@ enum diffie_hellman_group_t {
extern enum_name_t *diffie_hellman_group_names; extern enum_name_t *diffie_hellman_group_names;
/** /**
* @brief Implementation of the widely used Diffie-Hellman algorithm. * @brief Implementation of the Diffie-Hellman algorithm, as in RFC2631.
* *
* @b Constructors: * @b Constructors:
* - diffie_hellman_create() * - diffie_hellman_create()
* *
* @ingroup transforms * @ingroup crypto
*/ */
struct diffie_hellman_t { struct diffie_hellman_t {
/** /**
* @brief Returns the shared secret of this diffie hellman exchange. * @brief Returns the shared secret of this diffie hellman exchange.
* *
* @warning Space for returned secret is allocated and must be * Space for returned secret is allocated and must be
* freed by the caller. * freed by the caller.
* *
* @param this calling diffie_hellman_t object * @param this calling object
* @param[out] secret shared secret will be written into this chunk * @param secret shared secret will be written into this chunk
* @return * @return
* - SUCCESS * - SUCCESS
* - FAILED if not both DH values are set * - FAILED if not both DH values are set
*/ */
status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret); status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret);
/** /**
* @brief Sets the public value of partner. * @brief Sets the public value of partner.
* *
* chunk gets cloned and can be destroyed afterwards. * Chunk gets cloned and can be destroyed afterwards.
* *
* @param this calling diffie_hellman_t object * @param this calling object
* @param public_value public value of partner * @param value public value of partner
*/ */
void (*set_other_public_value) (diffie_hellman_t *this, chunk_t public_value); void (*set_other_public_value) (diffie_hellman_t *this, chunk_t value);
/** /**
* @brief Gets the public value of partner. * @brief Gets the public value of partner.
* *
* @warning Space for returned chunk is allocated and must be * Space for returned chunk is allocated and must be freed by the caller.
* freed by the caller.
* *
* @param this calling diffie_hellman_t object * @param this calling object
* @param[out] public_value public value of partner is stored at this location * @param value public value of partner is stored at this location
* @return * @return
* - SUCCESS * - SUCCESS
* - FAILED if other public value not set * - FAILED if other public value not set
*/ */
status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *public_value); status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *value);
/** /**
* @brief Gets the public value of caller * @brief Gets the own public value to transmit.
* *
* @warning Space for returned chunk is allocated and must be * Space for returned chunk is allocated and must be freed by the caller.
* freed by the caller.
* *
* @param this calling diffie_hellman_t object * @param this calling object
* @param[out] public_value public value of caller is stored at this location * @param value public value of caller is stored at this location
*/ */
void (*get_my_public_value) (diffie_hellman_t *this, chunk_t *public_value); void (*get_my_public_value) (diffie_hellman_t *this, chunk_t *value);
/** /**
* @brief Get the DH group used. * @brief Get the DH group used.
* *
* @param this calling diffie_hellman_t object * @param this calling object
* @return DH group set in construction * @return DH group set in construction
*/ */
diffie_hellman_group_t (*get_dh_group) (diffie_hellman_t *this); diffie_hellman_group_t (*get_dh_group) (diffie_hellman_t *this);
/** /**
* @brief Destroys an diffie_hellman_t object. * @brief Destroys an diffie_hellman_t object.
* *
* @param this diffie_hellman_t object to destroy * @param this diffie_hellman_t object to destroy
*/ */
void (*destroy) (diffie_hellman_t *this); void (*destroy) (diffie_hellman_t *this);
}; };
@@ -133,15 +131,14 @@ struct diffie_hellman_t {
/** /**
* @brief Creates a new diffie_hellman_t object. * @brief Creates a new diffie_hellman_t object.
* *
* The first diffie hellman public value gets automatically created. * @param group Diffie Hellman group number to use
*
* @param dh_group_number Diffie Hellman group number to use
* @return * @return
* - diffie_hellman_t object * - diffie_hellman_t object
* - NULL if dh group not supported * - NULL if dh group not supported
* *
* @ingroup transforms * @ingroup crypto
*/ */
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number); diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t group);
#endif /*DIFFIE_HELLMAN_H_*/ #endif /*DIFFIE_HELLMAN_H_*/