diff options
author | Jan Hutter <jhutter@hsr.ch> | 2005-11-18 08:19:12 +0000 |
---|---|---|
committer | Jan Hutter <jhutter@hsr.ch> | 2005-11-18 08:19:12 +0000 |
commit | 99400f979e2b22bee27d03549d478f45d473ee63 (patch) | |
tree | cd9632537a8a89edf9e264090188f6d0372dd7f8 /Source | |
parent | d768cb67902783f4275f08042d4f3ce6f1c0984a (diff) | |
download | strongswan-99400f979e2b22bee27d03549d478f45d473ee63.tar.bz2 strongswan-99400f979e2b22bee27d03549d478f45d473ee63.tar.xz |
- wrote diffie_hellman_t but not tested
Diffstat (limited to 'Source')
-rw-r--r-- | Source/charon/transforms/diffie_hellman.c | 400 | ||||
-rw-r--r-- | Source/charon/transforms/diffie_hellman.h | 112 | ||||
-rw-r--r-- | Source/charon/utils/gmp_helper.c | 1 | ||||
-rw-r--r-- | Source/charon/utils/gmp_helper.h | 2 |
4 files changed, 515 insertions, 0 deletions
diff --git a/Source/charon/transforms/diffie_hellman.c b/Source/charon/transforms/diffie_hellman.c new file mode 100644 index 000000000..6fceb2d08 --- /dev/null +++ b/Source/charon/transforms/diffie_hellman.c @@ -0,0 +1,400 @@ +/** + * @file diffie_hellman.c + * + * @brief Class to represent a diffie hellman exchange. + * + */ + +/* + * Copyright (C) 1998-2002 D. Hugh Redelmeier. + * Copyright (C) 1999, 2000, 2001 Henry Spencer. + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <gmp.h> + +#include "diffie_hellman.h" + +#include "../payloads/transform_substructure.h" +#include "../utils/allocator.h" +#include "../utils/randomizer.h" +#include "../utils/gmp_helper.h" + + +/** + * Modulus of Group 1 + */ +static u_int8_t group1_modulus[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34, + 0xC4,0xC6,0x62,0x8B,0x80 ,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74, + 0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, + 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37, + 0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6, + 0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF +}; + + +/** + * Entry of the modulus list + */ +typedef struct modulus_info_entry_s modulus_info_entry_t; + +struct modulus_info_entry_s{ + /** + * Group number as it is defined in transform_substructure.h + */ + diffie_hellman_group_t group; + + /** + * Pointer to first byte of modulus in (network order) + */ + u_int8_t *modulus; + + /* + * Length of modulus in bytes + */ + size_t modulus_length; + + /* + * Generator value + */ + u_int16_t generator; +}; + + +static modulus_info_entry_t modulus_info_entries[] = { + {MODP_768_BIT,group1_modulus,sizeof(group1_modulus),2}, +}; + +/** + * Private data of an diffie_hellman_t object. + * + */ +typedef struct private_diffie_hellman_s private_diffie_hellman_t; + +struct private_diffie_hellman_s { + /** + * public diffie_hellman_t interface + */ + diffie_hellman_t public; + + /** + * Diffie Hellman group number + */ + u_int16_t dh_group_number; + + /** + * Modulus + */ + mpz_t modulus; + + /** + * Modulus length + */ + size_t modulus_length; + + /* + * Generator value + */ + u_int16_t generator; + + /** + * My prime + */ + mpz_t my_prime; + + /** + * My public value + */ + mpz_t my_public_value; + + /** + * Other public value + */ + mpz_t other_public_value; + + /** + * Shared secret + */ + mpz_t shared_secret; + + /** + * True if public modulus is computed and stored in my_public_value + */ + bool my_public_value_is_computed; + + /** + * True if shared secret is computed and stored in my_public_value + */ + bool shared_secret_is_computed; + + /** + * helper class for gmp functions + */ + gmp_helper_t *gmp_helper; + + /** + * 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); +}; + +/* Compute DH shared secret from our local secret and the peer's public value. + * We make the leap that the length should be that of the group + * (see quoted passage at start of ACCEPT_KE). + */ +//static void +//compute_dh_shared(struct state *st, const chunk_t g +//, const struct oakley_group_desc *group) +//{ +// MP_INT mp_g, mp_shared; +// struct timeval tv0, tv1; +// unsigned long tv_diff; +// +// gettimeofday(&tv0, NULL); +// passert(st->st_sec_in_use); +// n_to_mpz(&mp_g, g.ptr, g.len); +// mpz_init(&mp_shared); +// mpz_powm(&mp_shared, &mp_g, &st->st_sec, group->modulus); +// mpz_clear(&mp_g); +// freeanychunk(st->st_shared); /* happens in odd error cases */ +// st->st_shared = mpz_to_n(&mp_shared, group->bytes); +// mpz_clear(&mp_shared); +// gettimeofday(&tv1, NULL); +// tv_diff=(tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec); +// DBG(DBG_CRYPT, +// DBG_log("compute_dh_shared(): time elapsed (%s): %ld usec" +// , enum_show(&oakley_group_names, st->st_oakley.group->group) +// , tv_diff); +// ); +// /* if took more than 200 msec ... */ +// if (tv_diff > 200000) { +// loglog(RC_LOG_SERIOUS, "WARNING: compute_dh_shared(): for %s took " +// "%ld usec" +// , enum_show(&oakley_group_names, st->st_oakley.group->group) +// , tv_diff); +// } +// +// DBG_cond_dump_chunk(DBG_CRYPT, "DH shared secret:\n", st->st_shared); +//} + + +/** + * Implements private_diffie_hellman_t's set_modulus function. + * See #private_diffie_hellman_t.set_modulus for description. + */ +static status_t set_modulus(private_diffie_hellman_t *this) +{ + int i; + status_t status = NOT_FOUND; + + 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; + this->gmp_helper->chunk_to_mpz(this->gmp_helper,&(this->modulus),modulus_chunk); + this->modulus_length = modulus_chunk.len; + this->generator = modulus_info_entries[i].generator; + status = SUCCESS; + break; + } + } + return status; +} + +/** + * Implements diffie_hellman_t's set_other_public_value function. + * See #diffie_hellman_t.set_other_public_value for description. + */ +static status_t set_other_public_value(private_diffie_hellman_t *this,chunk_t public_value) +{ + this->gmp_helper->chunk_to_mpz(this->gmp_helper,&(this->other_public_value),public_value); + this->compute_shared_secret(this); + return SUCCESS; +} + +/** + * Implements diffie_hellman_t's get_other_public_value function. + * See #diffie_hellman_t.get_other_public_value for description. + */ +static status_t get_other_public_value(private_diffie_hellman_t *this,chunk_t *public_value) +{ + if (!this->shared_secret_is_computed) + { + return FAILED; + } + return (this->gmp_helper->mpz_to_chunk(this->gmp_helper,&(this->other_public_value), public_value,this->modulus_length)); +} + +/** + * Implements private_diffie_hellman_t's compute_shared_secret function. + * See #private_diffie_hellman_t.compute_shared_secret for description. + */ +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_prime,this->modulus); + + this->shared_secret_is_computed = TRUE; +} + + +/** + * Implements private_diffie_hellman_t's compute_public_value function. + * See #private_diffie_hellman_t.compute_public_value for description. + */ +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_prime,this->modulus); + /* generator not used anymore */ + mpz_clear(generator); + this->my_public_value_is_computed = TRUE; +} + +/** + * Implements diffie_hellman_t's get_my_public_value function. + * See #diffie_hellman_t.get_my_public_value for description. + */ +static status_t get_my_public_value(private_diffie_hellman_t *this,chunk_t *public_value) +{ + if (!this->my_public_value_is_computed) + { + this->compute_public_value(this); + } + return (this->gmp_helper->mpz_to_chunk(this->gmp_helper,&(this->my_public_value), public_value,this->modulus_length)); +} + +/** + * Implements diffie_hellman_t's get_shared_secret function. + * See #diffie_hellman_t.get_shared_secret for description. + */ +static status_t get_shared_secret(private_diffie_hellman_t *this,chunk_t *secret) +{ + if (!this->shared_secret_is_computed) + { + return FAILED; + } + return (this->gmp_helper->mpz_to_chunk(this->gmp_helper,&(this->shared_secret), secret,this->modulus_length)); +} + +/** + * Implements diffie_hellman_t's destroy function. + * See #diffie_hellman_t.destroy for description. + */ +static status_t destroy(private_diffie_hellman_t *this) +{ + this->gmp_helper->destroy(this->gmp_helper); + mpz_clear(this->modulus); + mpz_clear(this->my_prime); + if (this->my_public_value_is_computed) + { + mpz_clear(this->my_public_value); + } + if (this->shared_secret_is_computed) + { + /* other public value gets initialized together with shared secret */ + mpz_clear(this->other_public_value); + mpz_clear(this->shared_secret); + } + + allocator_free(this); + return SUCCESS; +} + + +/* + * Described in header + */ +diffie_hellman_t *diffie_hellman_create(u_int16_t dh_group_number) +{ + private_diffie_hellman_t *this = allocator_alloc_thing(private_diffie_hellman_t); + if ((this == NULL)) + { + return NULL; + } + + /* public functions */ + this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; + this->public.set_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; + this->public.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; + this->public.get_my_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; + this->public.destroy = (status_t (*)(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; + + this->gmp_helper = gmp_helper_create(); + + if (this->gmp_helper == NULL) + { + allocator_free(this); + return NULL; + } + + /* set this->modulus */ + if (this->set_modulus(this) != SUCCESS) + { + this->gmp_helper->destroy(this->gmp_helper); + allocator_free(this); + return NULL; + } + + + if (this->gmp_helper->init_prime(this->gmp_helper,&(this->my_prime),10) != SUCCESS) + { + this->gmp_helper->destroy(this->gmp_helper); + allocator_free(this); + return NULL; + } + this->my_public_value_is_computed = FALSE; + this->shared_secret_is_computed = FALSE; + this->modulus_length = 0; + + return &(this->public); +} diff --git a/Source/charon/transforms/diffie_hellman.h b/Source/charon/transforms/diffie_hellman.h new file mode 100644 index 000000000..8313a140a --- /dev/null +++ b/Source/charon/transforms/diffie_hellman.h @@ -0,0 +1,112 @@ +/** + * @file diffie_hellman.h + * + * @brief Class to represent a diffie hellman exchange. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef DIFFIE_HELLMAN_H_ +#define DIFFIE_HELLMAN_H_ + +#include "../types.h" + +/** + * Object representing a diffie hellman exchange + * + */ +typedef struct diffie_hellman_s diffie_hellman_t; + +struct diffie_hellman_s { + + /** + * @brief Returns the shared secret of this diffie hellman exchange + * + * @warning Space for returned secret is allocated and has to get freed by the caller + * + * @param this calling diffie_hellman_t object + * @param[out] secret shared secret will be written into this chunk + * @return + * - SUCCESS + * - FAILED if not both DH values are set + * - OUT_OF_RES if out of ressources + */ + status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret); + + /** + * @brief Sets the public value of partner + * + * @warning chunk gets copied + * + * @param this calling diffie_hellman_t object + * @param public_value public value of partner + * @return + * - SUCCESS + * - OUT_OF_RES if out of ressources + */ + status_t (*set_other_public_value) (diffie_hellman_t *this, chunk_t public_value); + + /** + * @brief Gets the public value of partner + * + * @warning chunk gets copied + * + * @param this calling diffie_hellman_t object + * @param[out] public_value public value of partner is stored at this location + * @return + * - SUCCESS + * - OUT_OF_RES if out of ressources + * - FAILED if other public value not set + */ + status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *public_value); + + /** + * @brief Gets the public value of caller + * + * @warning chunk gets copied + * + * @param this calling diffie_hellman_t object + * @param[out] public_value public value of caller is stored at this location + * @return + * - SUCCESS + * - OUT_OF_RES if out of ressources + */ + status_t (*get_my_public_value) (diffie_hellman_t *this, chunk_t *public_value); + + /** + * @brief Destroys an diffie_hellman_t object. + * + * @param this diffie_hellman_t object to destroy + * @return + * SUCCESS in any case + */ + status_t (*destroy) (diffie_hellman_t *this); +}; + +/** + * Creates a new diffie_hellman_t object + * + * The first diffie hellman public value gets automatically created + * + * @param dh_group_number Diffie Hellman group number to use + * @return + * - diffie_hellman_t if successfully + * - NULL if out of ressources or dh_group not supported + */ +diffie_hellman_t *diffie_hellman_create(u_int16_t dh_group_number); + +#endif /*DIFFIE_HELLMAN_H_*/ diff --git a/Source/charon/utils/gmp_helper.c b/Source/charon/utils/gmp_helper.c index 6d6ddc52b..d9e2ec9f1 100644 --- a/Source/charon/utils/gmp_helper.c +++ b/Source/charon/utils/gmp_helper.c @@ -130,6 +130,7 @@ static status_t init_prime (private_gmp_helper_t *this, mpz_t *prime, int bytes) allocator_free(random_bytes.ptr); random_bytes.ptr = NULL; + /* composites are possible but should never occur */ mpz_nextprime (*(prime),*(prime)); return SUCCESS; diff --git a/Source/charon/utils/gmp_helper.h b/Source/charon/utils/gmp_helper.h index 478dd06a9..ff2a73c8a 100644 --- a/Source/charon/utils/gmp_helper.h +++ b/Source/charon/utils/gmp_helper.h @@ -54,6 +54,8 @@ struct gmp_helper_s { /* Convert network form (binary bytes, big-endian) to mpz_t of gmp library. * + * mpz_t gets initialized in this function. + * * @param this calling private_gmp_helper_t object * @param mpz_value pointer to a mpz_t value * @param data chunk_t containing the network form of data |