implemented an optional DH public value test
some other cleanups, using RFC2631 variable names
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_*/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user