Wiselib
wiselib.testing/algorithms/crypto/diffie_hellman_lite/diffie_hellman_algorithm.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  ** This file is part of the generic algorithm library Wiselib.           **
00003  ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project.      **
00004  **                                                                       **
00005  ** The Wiselib is free software: you can redistribute it and/or modify   **
00006  ** it under the terms of the GNU Lesser General Public License as        **
00007  ** published by the Free Software Foundation, either version 3 of the    **
00008  ** License, or (at your option) any later version.                       **
00009  **                                                                       **
00010  ** The Wiselib is distributed in the hope that it will be useful,        **
00011  ** but WITHOUT ANY WARRANTY; without even the implied warranty of        **
00012  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         **
00013  ** GNU Lesser General Public License for more details.                   **
00014  **                                                                       **
00015  ** You should have received a copy of the GNU Lesser General Public      **
00016  ** License along with the Wiselib.                                       **
00017  ** If not, see <http://www.gnu.org/licenses/>.                           **
00018  **                                                                       **
00019  ** Author: Christoph Knecht, University of Bern 2010                     **
00020  ***************************************************************************/
00021 #ifndef DIFFIE_HELLMAN_ALGORITHM_H
00022 #define DIFFIE_HELLMAN_ALGORITHM_H
00023 
00024 #include "util/base_classes/routing_base.h"
00025 #include "algorithm/diffie_hellman_message.h"
00026 #include "algorithm/diffie_hellman_list.h"
00027 #include "algorithm/diffie_hellman_crypto_handler.h"
00028 #include "algorithm/aes.h"
00029 #include <string.h>
00030 #ifdef SHAWN
00031 #include <stdlib.h>
00032 #endif
00033 
00034 namespace wiselib
00035 {
00047    template<typename OsModel_P,
00048             typename Routing_P,
00049             typename NodeidIntMap_P,
00050             typename Radio_P = typename OsModel_P::Radio,
00051             typename Debug_P = typename OsModel_P::Debug>
00052    class DiffieHellmanAlgorithm
00053       : public RoutingBase<OsModel_P, Radio_P>
00054    {
00055    public:
00056       typedef OsModel_P OsModel;
00057       typedef Routing_P RoutingType;
00058       typedef NodeidIntMap_P MapType;
00059       typedef Radio_P Radio;
00060       typedef Debug_P Debug;
00061 
00062       typedef typename OsModel::Timer Timer;
00063 
00064       typedef typename RoutingType::RoutingTable RoutingTable;
00065       typedef typename RoutingType::RoutingTableIterator RoutingTableIterator;
00066 
00067       typedef typename Radio::node_id_t node_id_t;
00068       typedef typename Radio::size_t size_t;
00069       typedef typename Radio::block_data_t block_data_t;
00070       typedef typename Radio::message_id_t message_id_t;
00071       typedef typename MapType::iterator MapTypeIterator;
00072 
00073       typedef typename Timer::millis_t millis_t;
00074 
00075       typedef DiffieHellmanAlgorithm<OsModel, RoutingType, MapType, Radio, Debug> self_type;
00076       typedef DiffieHellmanMessage<OsModel, Radio> Message;
00077       typedef self_type* self_pointer_t;
00078 
00079       inline DiffieHellmanAlgorithm();
00080       inline void enable();
00081       inline void disable();
00082       inline void send(  node_id_t, size_t, block_data_t* );
00083       inline void receive( node_id_t, size_t, block_data_t* );
00084 
00085       inline void set_routing_type( RoutingType* routing )
00086       { routing_ = routing; };
00087 
00088       inline RoutingType* routing_type()
00089       { return routing_; };
00090 
00091       inline void init( Radio& radio, Timer& timer, Debug& debug )
00092       {
00093          radio_ = &radio;
00094          timer_ = &timer;
00095          debug_ = &debug;
00096       }
00097 
00098    private:
00099       inline void generate_secret_();
00100       inline void send_hello_message_();
00101       inline void send_secret_exchange_message_( void* );
00102       inline void timer_elapsed_( void* );
00103 
00104       // subroutines called during reception
00105       inline void process_encrypted_message_( node_id_t, Message * );
00106       inline void process_hello_message_( node_id_t, Message * );
00107       inline void process_secret_exchange_message_( node_id_t, Message * );
00108 
00109       // returns some "random" time used for waiting
00110       inline millis_t random_work_period_()
00111       {
00112 #ifdef SHAWN
00113          seed_ = ( rand() * ( 1.0 / ( RAND_MAX + 1.0 ) ) ) * 60;
00114          return (millis_t)( seed_ + MIN_WORK_TIME ) * 1000;
00115 #endif
00116 #ifndef SHAWN
00117          seed_++;
00118          seed_ = seed_ % 63;
00119          return (millis_t)( work_period_[seed_] + MIN_WORK_TIME ) * 1000;
00120 #endif
00121       };
00122 
00123       Radio& radio()
00124       { return *radio_; }
00125 
00126       Timer& timer()
00127       { return *timer_; }
00128 
00129       Debug& debug()
00130       { return *debug_; }
00131 
00132       typename Radio::self_pointer_t radio_;
00133       typename Timer::self_pointer_t timer_;
00134       typename Debug::self_pointer_t debug_;
00135 
00136       RoutingType *routing_;
00137 
00138       int callback_id_;
00139       uint16_t seq_nr_;
00140       uint16_t seed_;
00141       uint8_t work_period_[64];
00142 
00143       // depending on the key-length, max determines the amount of 128 Bytes long messages there are to send
00144       uint8_t max_;
00145 
00146       // storage container for all the neighbouring nodes (including their public keys and the generated communication keys)
00147       MapType neighbour_map_;
00148 
00149       // public and private secrets (gmplib)
00150       mpz_t a_;
00151       mpz_t A_;
00152 
00153       mpz_t g_;
00154       gmp_randstate_t state_;
00155 
00156       DiffieHellmanCryptoHandler<OsModel, AES<OsModel> > crypto_handler_;
00157 
00158       // char array to hold the key in its string form
00159       int8_t A_c_[ KEY_LENGTH / 8 ];
00160 
00161       // char array to hold the hardcoded prime number
00162       const int8_t *prime_;
00163 
00164       enum MessageIds
00165       {
00166          HELLO = 120,
00167          SECRET_EXCHANGE = 121,
00168          ENCRYPTED_MESSAGE = 122
00169       };
00170    };
00171    // -----------------------------------------------------------------------
00172    // -----------------------------------------------------------------------
00173    // -----------------------------------------------------------------------
00174    template<typename OsModel_P,
00175             typename Routing_P,
00176             typename RoutingTable_P,
00177             typename Radio_P,
00178             typename Debug_P>
00179    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00180    DiffieHellmanAlgorithm()
00181       :  radio_ ( 0 ),
00182          timer_ ( 0 ),
00183          debug_ ( 0 ),
00184          callback_id_ ( 0 ),
00185          seq_nr_      ( 0 )
00186    {
00187       // Hardcoded, 4096 Bit Sophie-Germain Prime
00188       prime_ = ( int8_t* ) "\xaf\x0c\x85\x8d\xf6\xf0\x8f\xdf\x9c\x65\xc4\x6b\x86\x2b\x8a\x49"
00189                            "\xa8\x96\x43\xbc\x8b\xeb\x69\xd4\xfe\xca\xd6\xde\xa6\xaf\x8d\xc3"
00190                            "\x94\x38\x12\xbc\x93\x78\x9d\xba\x86\x11\x3a\xd7\x9a\xbf\x48\xbf"
00191                            "\x46\x09\x89\x47\xe7\x1e\x41\xa1\x36\x53\x3f\x60\x43\x6f\x90\xb8"
00192                            "\x9d\x53\x5d\xc3\x54\xeb\xd9\xcb\x6c\xf5\x7f\x55\x06\xd5\xb1\x8b"
00193                            "\xbc\xaa\x86\x19\x98\xf4\x05\x5b\x9e\xc3\x58\x2f\xa6\xc2\x16\x1f"
00194                            "\x75\xd0\x55\x42\xba\x4b\x2d\x54\x96\xb4\x11\x38\x54\xc6\xd1\x4f"
00195                            "\xb8\xbb\x93\x37\x05\x79\xba\xe0\xe1\xe6\x07\x7f\xd6\xef\xe6\x2e"
00196                            "\xd7\x44\xf6\x5a\x19\x12\xf7\x30\x59\x2e\x62\x1e\xc7\xd4\x59\x3c"
00197                            "\x1f\xf4\x16\x94\xac\xf6\x1b\xe2\x7b\xa5\xd2\x5e\xdf\x5e\xbf\xe3"
00198                            "\x33\x34\x61\x7a\x31\xb0\x89\xaa\x8a\xc8\xb8\xf9\x17\xf0\xd8\x18"
00199                            "\x53\x62\x57\x4c\x7c\xdf\xaf\x64\x62\x41\x49\xae\xc5\xc1\xa3\x97"
00200                            "\x28\x96\x14\xa9\xef\xdc\x52\x9f\x40\x84\xb0\x97\x83\x60\xec\xe1"
00201                            "\x0d\xd6\xeb\x9a\xd8\xbe\x04\x6f\xe7\xc9\x35\x76\x9a\x06\x8a\xf8"
00202                            "\xbf\x72\x56\x9e\x6e\x5b\x45\x4b\x58\x75\x4f\x35\x89\x2b\x91\x8f"
00203                            "\xa7\x30\xfe\xfa\x1e\xf4\x06\x7d\x64\xf3\x65\xdb\x72\x53\xd4\x9e"
00204                            "\xd9\xf0\x91\x93\xc8\x89\xb4\xa0\x78\xe6\x2b\xf5\x6b\x91\x04\xf9"
00205                            "\xac\xac\x2e\x2a\x38\x03\xdb\xbd\xf4\xd7\x69\x6e\x1a\x26\xf8\xb4"
00206                            "\x71\x59\xaf\x14\xf8\x55\x0c\x70\xd0\xdc\x9b\x1c\x36\x35\x32\x86"
00207                            "\xa2\x01\xe0\x42\x47\x4f\x2d\x46\x67\x37\xbb\x35\xc3\xb6\xa7\x54"
00208                            "\x41\x3e\xaa\xd1\x90\xdd\x3d\x09\x08\x17\xbc\x32\xf6\xe7\xba\x41"
00209                            "\x3f\xf9\xf9\x4b\xf6\x5b\xa8\x76\x54\x5a\x4a\x1e\x0c\xe5\x44\x30"
00210                            "\x84\xf7\x04\x94\x22\x24\xee\x79\xf0\x67\xd8\x51\x86\x52\xb6\x1d"
00211                            "\x59\x1a\xa1\xbe\x7a\x35\xac\xd3\xd9\x6b\x31\x44\x3d\x30\x46\xb6"
00212                            "\x1c\x73\xd2\xa4\x13\x05\x84\x8a\xcc\xe6\x4d\x83\x04\x54\xf1\xa9"
00213                            "\x47\x60\x4b\x57\x62\x59\x90\x05\x9b\x23\xa2\xc3\xf3\x3c\xca\xcf"
00214                            "\x0a\x91\x85\xbf\x9e\x6b\xbf\x9c\xcc\x7e\xd0\x5e\xcc\xbe\xe8\xed"
00215                            "\xa9\x37\x5a\x96\x4f\xd1\xf0\xc4\xe0\xfb\x25\xe6\x4a\xf1\x90\x89"
00216                            "\xfd\xb9\xa3\x5a\xbc\xb1\x7e\x8c\x4b\xfd\xfd\x60\x29\x48\x31\x94"
00217                            "\x28\x51\xcd\x22\x7a\x0c\x0f\x40\x5a\x84\xdb\xb4\x37\x90\x91\x90"
00218                            "\x18\x1b\x3e\xf7\x79\x1b\x47\x37\x02\x0f\xf1\x2a\x0d\xef\x48\x0b"
00219                            "\x78\x08\x40\xce\xde\x5f\x62\x4c\xf8\xf3\xbe\xf5\xfd\x44\xf5\x73";
00220 
00221       // intialize stuff (number of 128 Bytes parts)
00222       max_ = KEY_LENGTH / 1024;
00223 
00224       mpz_init2( a_, KEY_LENGTH );
00225       mpz_init2( A_, KEY_LENGTH );
00226 
00227       mpz_init2( g_, 2 );
00228       mpz_set_ui( g_, 2 );
00229 
00230       gmp_randinit_default( state_ );
00231    }
00232    // -----------------------------------------------------------------------
00233    template<typename OsModel_P,
00234             typename Routing_P,
00235             typename RoutingTable_P,
00236             typename Radio_P,
00237             typename Debug_P>
00238    void
00239    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00240    enable()
00241    {
00242 #ifdef DEBUG_DH
00243       debug().debug( "DiffieHellmanAlgorithm: Booting (Node %i)\n", radio().id() );
00244 #endif
00245 
00246 #ifdef SHAWN
00247       srand ( time( NULL ) * ( 3 * radio().id() + 2 ) );
00248 #endif
00249 
00250       seed_ = radio().id();
00251 
00252       work_period_[0] = 29;
00253       work_period_[1] = 25;
00254       work_period_[2] = 43;
00255       work_period_[3] = 36;
00256       work_period_[4] = 52;
00257       work_period_[5] = 10;
00258       work_period_[6] = 53;
00259       work_period_[7] = 5;
00260       work_period_[8] = 23;
00261       work_period_[9] = 58;
00262       work_period_[10] = 56;
00263       work_period_[11] = 29;
00264       work_period_[12] = 53;
00265       work_period_[13] = 21;
00266       work_period_[14] = 41;
00267       work_period_[15] = 0;
00268       work_period_[16] = 20;
00269       work_period_[17] = 13;
00270       work_period_[18] = 54;
00271       work_period_[19] = 29;
00272       work_period_[20] = 43;
00273       work_period_[21] = 20;
00274       work_period_[22] = 4;
00275       work_period_[23] = 22;
00276       work_period_[24] = 2;
00277       work_period_[25] = 42;
00278       work_period_[26] = 0;
00279       work_period_[27] = 28;
00280       work_period_[28] = 52;
00281       work_period_[29] = 28;
00282       work_period_[30] = 40;
00283       work_period_[31] = 21;
00284       work_period_[32] = 54;
00285       work_period_[33] = 23;
00286       work_period_[34] = 58;
00287       work_period_[35] = 46;
00288       work_period_[36] = 33;
00289       work_period_[37] = 51;
00290       work_period_[38] = 52;
00291       work_period_[39] = 57;
00292       work_period_[40] = 50;
00293       work_period_[41] = 49;
00294       work_period_[42] = 27;
00295       work_period_[43] = 44;
00296       work_period_[44] = 10;
00297       work_period_[45] = 8;
00298       work_period_[46] = 44;
00299       work_period_[47] = 31;
00300       work_period_[48] = 22;
00301       work_period_[49] = 39;
00302       work_period_[50] = 0;
00303       work_period_[51] = 5;
00304       work_period_[52] = 59;
00305       work_period_[53] = 5;
00306       work_period_[54] = 27;
00307       work_period_[55] = 2;
00308       work_period_[56] = 47;
00309       work_period_[57] = 28;
00310       work_period_[58] = 31;
00311       work_period_[59] = 40;
00312       work_period_[60] = 56;
00313       work_period_[61] = 11;
00314       work_period_[62] = 2;
00315       work_period_[63] = 50;
00316 
00317       millis_t time = random_work_period_();
00318 
00319       generate_secret_();
00320 
00321       radio().enable_radio();
00322       radio().template reg_recv_callback<self_type, &self_type::receive>( this );
00323       routing_->template reg_recv_callback<self_type, &self_type::receive>( this );
00324       timer().template set_timer<self_type, &self_type::timer_elapsed_>( time, this, 0 );
00325    }
00326    // -----------------------------------------------------------------------
00327    template<typename OsModel_P,
00328             typename Routing_P,
00329             typename RoutingTable_P,
00330             typename Radio_P,
00331             typename Debug_P>
00332    void
00333    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00334    disable()
00335    {
00336 #ifdef DEBUG_DH
00337       debug().debug( "DiffieHellmanAlgorithm: Disable\n" );
00338 #endif
00339 
00340       routing_->unreg_recv_callback();
00341    }
00342    // -----------------------------------------------------------------------
00343    // receives messages and parses them according to their content
00344    template<typename OsModel_P,
00345             typename Routing_P,
00346             typename RoutingTable_P,
00347             typename Radio_P,
00348             typename Debug_P>
00349    void
00350    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00351    receive( node_id_t from, size_t len, block_data_t *data )
00352    {
00353       if( from == radio().id() )
00354          return;
00355 
00356       message_id_t msg_id = *data;
00357       Message *message = (Message *)data;
00358 
00359       switch( msg_id )
00360       {
00361          // we received a hello message
00362          case HELLO:
00363             process_hello_message_( from, message );
00364             break;
00365          // we got a part of a neighbouring node's public secret
00366          case SECRET_EXCHANGE:
00367             process_secret_exchange_message_( from, message );
00368             break;
00369          // some encrypted content was sent over the network
00370          case ENCRYPTED_MESSAGE:
00371             process_encrypted_message_( from, message );
00372             break;
00373       }
00374    }
00375    // -----------------------------------------------------------------------
00376    // generates a random number and establishes a public and a private key
00377    template<typename OsModel_P,
00378             typename Routing_P,
00379             typename RoutingTable_P,
00380             typename Radio_P,
00381             typename Debug_P>
00382    void
00383    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00384    generate_secret_()
00385    {
00386       gmp_randseed_ui( state_, time( NULL ) * ( 1 + radio().id() ) );
00387 
00388       mpz_t p;
00389       mpz_init2( p, KEY_LENGTH );
00390       mpz_import( p, KEY_LENGTH / 8, 1, 1, 0, 0, prime_ );
00391 
00392       mpz_sub_ui( p, p, 2 );
00393       mpz_urandomm( a_, state_, p );
00394       mpz_add_ui( p, p, 2 );
00395       mpz_add_ui( a_, a_, 1 );
00396 
00397       mpz_powm( A_, g_, a_, p );
00398 
00399       memset( A_c_, '\0', KEY_LENGTH / 8 );
00400       mpz_export( A_c_, NULL, 1, 1, 0, 0, A_ );
00401    }
00402    // -----------------------------------------------------------------------
00403    // sends a new message containing a part of the own public key (amount of messages to send determined by max_)
00404    template<typename OsModel_P,
00405             typename Routing_P,
00406             typename RoutingTable_P,
00407             typename Radio_P,
00408             typename Debug_P>
00409    void
00410    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00411    send_secret_exchange_message_( void* userdata )
00412    {
00413 #ifdef DEBUG_DH
00414       debug().debug( "DiffieHellmanAlgorithm: Broadcasting Public Secret (Node %i)\n", radio().id() );
00415 #endif
00416 
00417       uint8_t i;
00418       Message message;
00419       message.set_msg_id( SECRET_EXCHANGE );
00420       message.set_node_id( radio().id() );
00421 
00422       seq_nr_ = 0;
00423 
00424       for( i = 0; i < max_; i++ )
00425       {
00426          message.set_seq_nr( seq_nr_++ );
00427          message.set_payload( 128, (uint8_t*)( &A_c_[ i * 128 ] ) );
00428 
00429          radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message );
00430       }
00431    }
00432    // -----------------------------------------------------------------------
00433    template<typename OsModel_P,
00434             typename Routing_P,
00435             typename RoutingTable_P,
00436             typename Radio_P,
00437             typename Debug_P>
00438    void
00439    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00440    send( node_id_t destination, size_t len, block_data_t *data )
00441    {
00442 #ifdef DEBUG_DH
00443       debug().debug( "DiffieHellmanAlgorithm: Sending encrypted Message to Node %i (Node %i)\n", destination, radio().id() );
00444 #endif
00445 
00446       Message message;
00447       message.set_msg_id( ENCRYPTED_MESSAGE );
00448       message.set_node_id( radio().id() );
00449       message.set_dest_id( destination );
00450 
00451       message.set_seq_nr( 1 );
00452 
00453       // find the next hop to send the message to
00454       RoutingTable *table = routing_->routing_table();
00455       RoutingTableIterator it = table->find( destination );
00456 
00457       if( it != table->end() && it->second.next_hop != radio().NULL_NODE_ID )
00458       {
00459          // AES has fixed size 16 Bytes Blocks
00460          uint16_t length_aes = ( len / 16 + 1 ) * 16;
00461 
00462          MapTypeIterator itt = neighbour_map_.find( it->second.next_hop );
00463 
00464          if( itt != neighbour_map_.end() )
00465          {
00466             const uint8_t *key = itt->second.key();
00467             uint8_t encrypted[ length_aes ];
00468 
00469             // encrypt it
00470             crypto_handler_.key_setup( (uint8_t*)key );
00471             crypto_handler_.encrypt( data, encrypted, length_aes );
00472 
00473             message.set_payload( length_aes, encrypted );
00474 
00475             routing_->send( it->second.next_hop, message.buffer_size(), (uint8_t*)&message );
00476          }
00477       }
00478    }
00479    // -----------------------------------------------------------------------
00480    template<typename OsModel_P,
00481             typename Routing_P,
00482             typename RoutingTable_P,
00483             typename Radio_P,
00484             typename Debug_P>
00485    void
00486    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00487    process_secret_exchange_message_( node_id_t from, Message *message )
00488    {
00489       uint8_t seq_nr = ( uint8_t )message->seq_nr();
00490       uint8_t* data = message->payload();
00491       MapTypeIterator it = neighbour_map_.find( message->node_id() );
00492 
00493       // checks whether node entry does not yet exist in seq_map (no key has been setup)
00494       if ( it == neighbour_map_.end() )
00495       {
00496 #ifdef DEBUG_DH
00497          debug().debug( "DiffieHellmanAlgorithm: Got part %d of Node %d's public secret (Node %i)\n", (seq_nr+1), from, radio().id() );
00498 #endif
00499 
00500          DiffieHellmanList diffie_data;
00501          diffie_data.set_B( (const int8_t*)data, seq_nr );
00502          neighbour_map_[ message->node_id() ] = diffie_data;
00503       }
00504       else
00505       {
00506          if( !(it->second.is_initialized()) )
00507          {
00508 #ifdef DEBUG_DH
00509             debug().debug( "DiffieHellmanAlgorithm: Got part %d of Node %d's public secret (Node %i)\n", (seq_nr+1), from, radio().id() );
00510 #endif
00511 
00512             uint8_t all_set = it->second.set_B( (const int8_t*)data, seq_nr );
00513 
00514             // this was the last part of the key - therefore we can now calculate the final key
00515             if( all_set )
00516             {
00517 #ifdef DEBUG_DH
00518                debug().debug( "DiffieHellmanAlgorithm: Got all parts of Node %d's public secret (Node %i)\n", from, radio().id() );
00519                debug().debug( "DiffieHellmanAlgorithm: Calculating Key to Node %d now (Node %i)\n", from, radio().id() );
00520 #endif
00521 
00522                mpz_t p;
00523                mpz_init2( p, KEY_LENGTH );
00524                mpz_import( p, KEY_LENGTH / 8, 1, 1, 0, 0, prime_ );
00525 
00526                it->second.generate_key( a_, p );
00527                it->second.set_is_initialized();
00528             }
00529          }
00530       }
00531    }
00532    // -----------------------------------------------------------------------
00533    template<typename OsModel_P,
00534             typename Routing_P,
00535             typename RoutingTable_P,
00536             typename Radio_P,
00537             typename Debug_P>
00538    void
00539    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00540    process_encrypted_message_( node_id_t from, Message *message )
00541    {
00542       MapTypeIterator it = neighbour_map_.find( from );
00543 
00544       if( it != neighbour_map_.end() )
00545       {
00546          const uint8_t *key = it->second.key();
00547          uint16_t payload_size = message->payload_size();
00548          uint8_t deciphered[ payload_size ];
00549 
00550          // decrypt it
00551          crypto_handler_.key_setup( (uint8_t*)key );
00552          crypto_handler_.decrypt( message->payload(), deciphered, payload_size );
00553 
00554          // the message has not reached its destination yet
00555          if( message->dest_id() != radio().id() )
00556          {
00557 #ifdef DEBUG_DH
00558             debug().debug( "DiffieHellmanAlgorithm: Received Message for Node %i - Forwarding Now... (Node %i)\n", message->dest_id(), radio().id() );
00559 #endif
00560 
00561             RoutingTable *table = routing_->routing_table();
00562             RoutingTableIterator it = table->find( message->dest_id() );
00563             if( it != table->end() && it->second.next_hop != radio().NULL_NODE_ID )
00564             {
00565                key = ( neighbour_map_[ it->second.next_hop ] ).key();
00566 
00567                // encrypt it
00568                crypto_handler_.key_setup( (uint8_t*)key );
00569                crypto_handler_.encrypt( deciphered, deciphered, payload_size );
00570                message->set_payload( payload_size, deciphered );
00571 
00572                routing_->send( it->second.next_hop, message->buffer_size(), (uint8_t*)message );
00573             }
00574          }
00575          // the message has reached its destination
00576          else
00577          {
00578 #ifdef DEBUG_DH
00579             debug().debug( "DiffieHellmanAlgorithm: Received Message from Node %i (Node %i)\n", message->node_id(), radio().id() );
00580 #endif
00581 
00582             notify_receivers( message->node_id(), payload_size, deciphered );
00583          }
00584       }
00585    }
00586    // -----------------------------------------------------------------------
00587    template<typename OsModel_P,
00588             typename Routing_P,
00589             typename RoutingTable_P,
00590             typename Radio_P,
00591             typename Debug_P>
00592    void
00593    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00594    timer_elapsed_( void* userdata )
00595    {
00596 #ifdef DEBUG_DH
00597       debug().debug( "DiffieHellmanAlgorithm: Execute TimerElapsed (Node %i)\n", radio().id() );
00598 #endif
00599       millis_t time = random_work_period_();
00600 #ifdef DEBUG_DH
00601       debug().debug( "DiffieHellmanAlgorithm: Using %ims as new Timersetting ", time );
00602       debug().debug( "(Node %i)\n", radio().id() );
00603 #endif
00604 
00605       send_hello_message_();
00606       timer().template set_timer<self_type, &self_type::timer_elapsed_>( time, this, 0 );
00607    }
00608    // -----------------------------------------------------------------------
00609    // we append a list of all known neighbours as payload. therefore,
00610    // a receiving node knows whether or not to broadcast its public secret
00611    template<typename OsModel_P,
00612             typename Routing_P,
00613             typename RoutingTable_P,
00614             typename Radio_P,
00615             typename Debug_P>
00616    void
00617    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00618    send_hello_message_()
00619    {
00620 #ifdef DEBUG_DH
00621       debug().debug( "DiffieHellmanAlgorithm: Broadcasting Hello (Node %i)\n", radio().id() );
00622 #endif
00623 
00624       uint8_t size = neighbour_map_.size();
00625       uint8_t got[ size * 2 ];
00626       uint8_t i = 0;
00627 
00628       for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it )
00629       {
00630          uint16_t temp = it->first;
00631          memcpy( got + i * 2, &temp, 2);
00632          i++;
00633       }
00634 
00635       Message message;
00636       message.set_msg_id( HELLO );
00637       message.set_node_id( radio().id() );
00638       message.set_seq_nr( 1 );
00639       message.set_payload( size * 2, (block_data_t*)got );
00640 
00641       radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message );
00642    }
00643    // -----------------------------------------------------------------------
00644    template<typename OsModel_P,
00645             typename Routing_P,
00646             typename RoutingTable_P,
00647             typename Radio_P,
00648             typename Debug_P>
00649    void
00650    DiffieHellmanAlgorithm<OsModel_P, Routing_P, RoutingTable_P, Radio_P, Debug_P>::
00651    process_hello_message_( node_id_t from, Message *message )
00652    {
00653       MapTypeIterator it = neighbour_map_.find( message->node_id() );
00654 
00655       uint8_t size = message->payload_size();
00656       uint8_t i = 0;
00657       uint8_t flag = 1;
00658 
00659       // check whether we are in the list of known neighbours - if true, no need to send the public secret
00660       for(i = 0; i < size; i += 2 )
00661       {
00662          uint16_t cand;
00663          memcpy( &cand, message->payload() + i, 2 );
00664 
00665          if( cand == radio().id() )
00666             flag = 0;
00667       }
00668 
00669       // check whether someone needs our public secret - if true broadcast it!
00670       if( flag )
00671       {
00672 #ifdef DEBUG_DH
00673          debug().debug( "DiffieHellmanAlgorithm: Node %i needs our Public Secret (Node %i)\n", message->node_id(), radio().id() );
00674 #endif
00675          // wait a random time before broadcasting the public secret
00676          millis_t time = ( random_work_period_() - MIN_WORK_TIME * 1000 ) / 30;
00677          timer().template set_timer<self_type, &self_type::send_secret_exchange_message_>( time, this, 0 );
00678       }
00679    }
00680 }
00681 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines