- wrote diffie_hellman_t but not tested
authorJan Hutter <jhutter@hsr.ch>
Fri, 18 Nov 2005 08:19:12 +0000 (08:19 -0000)
committerJan Hutter <jhutter@hsr.ch>
Fri, 18 Nov 2005 08:19:12 +0000 (08:19 -0000)
Source/charon/transforms/diffie_hellman.c [new file with mode: 0644]
Source/charon/transforms/diffie_hellman.h [new file with mode: 0644]
Source/charon/utils/gmp_helper.c
Source/charon/utils/gmp_helper.h

diff --git a/Source/charon/transforms/diffie_hellman.c b/Source/charon/transforms/diffie_hellman.c
new file mode 100644 (file)
index 0000000..6fceb2d
--- /dev/null
@@ -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 (file)
index 0000000..8313a14
--- /dev/null
@@ -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_*/
index 6d6ddc5..d9e2ec9 100644 (file)
@@ -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;
index 478dd06..ff2a73c 100644 (file)
@@ -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