Wiselib
|
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