cleanups, fixes and simplification of diffie hellman code

This commit is contained in:
Martin Willi
2007-10-04 12:08:11 +00:00
parent a7e65d5262
commit 40f10fd88e
+96 -123
View File
@@ -29,6 +29,7 @@
#include "diffie_hellman.h" #include "diffie_hellman.h"
#include <utils/randomizer.h> #include <utils/randomizer.h>
#include <debug.h>
ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT, ENUM_BEGIN(diffie_hellman_group_names, MODP_NONE, MODP_1024_BIT,
"MODP_NONE", "MODP_NONE",
@@ -302,12 +303,12 @@ static u_int8_t group18_modulus[] = {
0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 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. * 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. * Group number as it is defined in file transform_substructure.h.
*/ */
@@ -329,19 +330,18 @@ struct modulus_info_entry_t {
u_int16_t generator; u_int16_t generator;
}; };
/** /**
* All supported modulus values. * All supported modulus values.
*/ */
static modulus_info_entry_t modulus_info_entries[] = { static modulus_entry_t modulus_entries[] = {
{MODP_768_BIT,group1_modulus,sizeof(group1_modulus),2}, {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 2},
{MODP_1024_BIT,group2_modulus,sizeof(group2_modulus),2}, {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 2},
{MODP_1536_BIT,group5_modulus,sizeof(group5_modulus),2}, {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 2},
{MODP_2048_BIT,group14_modulus,sizeof(group14_modulus),2}, {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 2},
{MODP_3072_BIT,group15_modulus,sizeof(group15_modulus),2}, {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 2},
{MODP_4096_BIT,group16_modulus,sizeof(group16_modulus),2}, {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 2},
{MODP_6144_BIT,group17_modulus,sizeof(group17_modulus),2}, {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 2},
{MODP_8192_BIT,group18_modulus,sizeof(group18_modulus),2}, {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 2},
}; };
typedef struct private_diffie_hellman_t private_diffie_hellman_t; typedef struct private_diffie_hellman_t private_diffie_hellman_t;
@@ -379,150 +379,106 @@ struct private_diffie_hellman_t {
/** /**
* My private value . * My private value .
*/ */
mpz_t my_private_value; mpz_t private;
/** /**
* My public value. * My public value.
*/ */
mpz_t my_public_value; mpz_t my_public;
/** /**
* Other public value. * Other public value.
*/ */
mpz_t other_public_value; mpz_t other_public;
/** /**
* Shared secret. * Shared secret.
*/ */
mpz_t shared_secret; mpz_t secret;
/** /**
* True if shared secret is computed and stored in my_public_value. * True if shared secret is computed and stored in my_public_value.
*/ */
bool shared_secret_is_computed; bool 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
*/
status_t (*set_modulus) (private_diffie_hellman_t *this);
/**
* Makes sure my public value is computed.
*
* @param this calling object
*/
void (*compute_public_value) (private_diffie_hellman_t *this);
/**
* Computes shared secret (other public value must be available).
*
* @param this calling object
*/
void (*compute_shared_secret) (private_diffie_hellman_t *this);
}; };
/** /**
* Implementation of private_diffie_hellman_t.set_modulus. * Compute the shared secret
*/ */
static status_t set_modulus(private_diffie_hellman_t *this) static void compute_shared_secret(private_diffie_hellman_t *this)
{ {
int i; mpz_powm(this->secret, this->other_public, this->private, this->modulus);
status_t status = NOT_FOUND; this->computed = TRUE;
for (i = 0; i < (sizeof(modulus_info_entries) / sizeof(modulus_info_entry_t)); i++)
{
if (modulus_info_entries[i].group == this->dh_group_number)
{
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;
}
}
return status;
} }
/** /**
* 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 public_value) static void set_other_public_value(private_diffie_hellman_t *this, chunk_t value)
{ {
mpz_import(this->other_public_value, public_value.len, 1, 1, 1, 0, public_value.ptr); mpz_import(this->other_public, value.len, 1, 1, 1, 0, value.ptr);
this->compute_shared_secret(this);
/* check public value: */
/* 1. 0 or 1 wouldn't include your generated value */
/* 2. a public value larger or equal the modulus is invalid anyway */
if (mpz_cmp_ui(this->other_public, 1) <= 0 ||
mpz_cmp(this->other_public, this->modulus) >= 0)
{
DBG1("public DH value verification failed: 0/1");
return;
}
compute_shared_secret(this);
} }
/** /**
* Implementation of diffie_hellman_t.get_other_public_value. * 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; return FAILED;
} }
public_value->len = this->modulus_length; value->len = this->modulus_length;
public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->other_public_value); value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->other_public);
return SUCCESS; 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. * Implementation of private_diffie_hellman_t.compute_public_value.
*/ */
static void compute_public_value (private_diffie_hellman_t *this) static void compute_public_value(private_diffie_hellman_t *this)
{ {
mpz_t generator; mpz_t generator;
/* initialize generator and set it*/
mpz_init_set_ui (generator,this->generator); mpz_init_set_ui(generator, this->generator);
/* initialize my public value */ mpz_powm(this->my_public, generator, this->private, this->modulus);
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); 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 *public_value) static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *value)
{ {
public_value->len = this->modulus_length; value->len = this->modulus_length;
public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->my_public_value); value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->my_public);
} }
/** /**
* Implementation of diffie_hellman_t.get_shared_secret. * 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; return FAILED;
} }
secret->len = this->modulus_length; secret->len = this->modulus_length;
secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->shared_secret); secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->secret);
return SUCCESS; return SUCCESS;
} }
@@ -534,21 +490,41 @@ static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this)
return this->dh_group_number; return this->dh_group_number;
} }
/**
* Lookup the modulus in modulo table
*/
static status_t set_modulus(private_diffie_hellman_t *this)
{
int i;
status_t status = NOT_FOUND;
for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++)
{
if (modulus_entries[i].group == this->dh_group_number)
{
chunk_t chunk;
chunk.ptr = modulus_entries[i].modulus;
chunk.len = modulus_entries[i].modulus_length;
mpz_import(this->modulus, chunk.len, 1, 1, 1, 0, chunk.ptr);
this->modulus_length = chunk.len;
this->generator = modulus_entries[i].generator;
status = SUCCESS;
break;
}
}
return status;
}
/** /**
* Implementation of diffie_hellman_t.destroy. * Implementation of diffie_hellman_t.destroy.
*/ */
static void destroy(private_diffie_hellman_t *this) static void destroy(private_diffie_hellman_t *this)
{ {
mpz_clear(this->modulus); mpz_clear(this->modulus);
mpz_clear(this->my_private_value); mpz_clear(this->private);
mpz_clear(this->my_public_value); mpz_clear(this->my_public);
mpz_clear(this->other_public_value); mpz_clear(this->other_public);
mpz_clear(this->secret);
if (this->shared_secret_is_computed)
{
/* other public value gets initialized together with shared secret */
mpz_clear(this->shared_secret);
}
free(this); free(this);
} }
@@ -559,7 +535,7 @@ diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number)
{ {
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_bytes; chunk_t random;
/* 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;
@@ -569,44 +545,41 @@ 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.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group;
this->public.destroy = (void (*)(diffie_hellman_t *)) destroy; 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 */ /* private variables */
this->dh_group_number = dh_group_number; this->dh_group_number = dh_group_number;
mpz_init(this->modulus); mpz_init(this->modulus);
mpz_init(this->other_public_value); mpz_init(this->other_public);
mpz_init(this->my_private_value); mpz_init(this->my_public);
mpz_init(this->private);
mpz_init(this->secret);
this->computed = FALSE;
/* set this->modulus */ /* set this->modulus */
if (this->set_modulus(this) != SUCCESS) if (set_modulus(this) != SUCCESS)
{ {
free(this); destroy(this);
return NULL; return NULL;
} }
randomizer = randomizer_create(); randomizer = randomizer_create();
if (randomizer == NULL) if (randomizer == NULL)
{ {
free(this); destroy(this);
return NULL; return NULL;
} }
if (randomizer->allocate_pseudo_random_bytes(randomizer, this->modulus_length, &random_bytes) != SUCCESS) if (randomizer->allocate_pseudo_random_bytes(randomizer,
this->modulus_length, &random) != SUCCESS)
{ {
randomizer->destroy(randomizer); randomizer->destroy(randomizer);
free(this); destroy(this);
return NULL; return NULL;
} }
mpz_import(this->my_private_value, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr); mpz_import(this->private, random.len, 1, 1, 1, 0, random.ptr);
chunk_free(&random_bytes); chunk_free(&random);
randomizer->destroy(randomizer); randomizer->destroy(randomizer);
this->compute_public_value(this); compute_public_value(this);
this->shared_secret_is_computed = FALSE; return &this->public;
return &(this->public);
} }