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 ESCHENAUER_GLIGOR_ALGORITHM_H 00022 #define ESCHENAUER_GLIGOR_ALGORITHM_H 00023 00024 #include <math.h> 00025 #include "util/base_classes/routing_base.h" 00026 #include "algorithm/eschenauer_gligor_message.h" 00027 #include "algorithm/eschenauer_gligor_crypto_handler.h" 00028 #include "algorithm/eschenauer_gligor_config.h" 00029 #include "algorithm/aes.h" 00030 #ifdef SHAWN 00031 #include <stdlib.h> 00032 #endif 00033 00034 // this part is used to patch the files manually 00035 #ifndef SHAWN 00036 static const uint8_t keys[ RING_SIZE * 16 ] = "aa22bbbbcccc"; 00037 uint8_t identifiers[ RING_SIZE * 2 + NEIGHBOUR_COUNT * 2 ] = "aa11bbbbcccc"; 00038 uint8_t backup_keys[ NEIGHBOUR_COUNT * 16 ] = "aa00bbbbcccc"; 00039 #endif 00040 00041 namespace wiselib 00042 { 00052 template<typename OsModel_P, 00053 typename Routing_P, 00054 typename NodeidIntMap_P, 00055 typename Radio_P = typename OsModel_P::Radio, 00056 typename Debug_P = typename OsModel_P::Debug> 00057 class EschenauerGligorAlgorithm 00058 : public RoutingBase<OsModel_P, Radio_P> 00059 { 00060 public: 00061 typedef OsModel_P OsModel; 00062 typedef Routing_P RoutingType; 00063 typedef NodeidIntMap_P MapType; 00064 typedef Radio_P Radio; 00065 typedef Debug_P Debug; 00066 00067 typedef typename OsModel::Timer Timer; 00068 00069 typedef typename RoutingType::RoutingTable RoutingTable; 00070 typedef typename RoutingType::RoutingTableIterator RoutingTableIterator; 00071 00072 typedef typename Radio::node_id_t node_id_t; 00073 typedef typename Radio::size_t size_t; 00074 typedef typename Radio::block_data_t block_data_t; 00075 typedef typename Radio::message_id_t message_id_t; 00076 typedef typename MapType::iterator MapTypeIterator; 00077 00078 typedef typename Timer::millis_t millis_t; 00079 00080 typedef EschenauerGligorAlgorithm<OsModel, RoutingType, MapType, Radio, Debug> self_type; 00081 typedef EschenaurGligorMessage<OsModel, Radio> Message; 00082 typedef self_type* self_pointer_t; 00083 00084 inline EschenauerGligorAlgorithm(); 00085 inline void enable(); 00086 inline void disable(); 00087 inline void send( node_id_t, size_t, block_data_t* ); 00088 inline void receive( node_id_t, size_t, block_data_t* ); 00089 00090 inline void set_routing_type( RoutingType* routing ) 00091 { routing_ = routing; }; 00092 00093 inline RoutingType* routing_type() 00094 { return routing_; }; 00095 00096 inline void init( Radio& radio, Timer& timer, Debug& debug ) 00097 { 00098 radio_ = &radio; 00099 timer_ = &timer; 00100 debug_ = &debug; 00101 } 00102 00103 // automatic patching (during runtime) by Shawn 00104 #ifdef SHAWN 00105 uint8_t identifiers[ RING_SIZE * 2 + NEIGHBOUR_COUNT * 2 ]; 00106 uint8_t keys[ RING_SIZE * 16 ]; 00107 uint8_t backup_keys[ NEIGHBOUR_COUNT * 16 ]; 00108 #endif 00109 00110 private: 00111 inline void key_proposal_( node_id_t, node_id_t, node_id_t ); 00112 inline void print_ring_(); 00113 inline void print_neighbours_(); 00114 inline void send_identifier_list_(); 00115 inline void send_key_proposal_( node_id_t, node_id_t, node_id_t, uint16_t ); 00116 inline void send_neighbour_list_( node_id_t ); 00117 inline void send_neighbour_request_( node_id_t ); 00118 inline void timer_elapsed_( void* ); 00119 00120 // subroutines called during reception 00121 inline void process_encrypted_message_( node_id_t, Message * ); 00122 inline void process_exchange_identifiers_( node_id_t, Message * ); 00123 inline void process_key_proposal_( node_id_t, Message * ); 00124 inline void process_neighbour_list_( node_id_t, Message *, uint8_t ); 00125 inline void process_neighbour_request_( node_id_t, Message * ); 00126 inline void work_neighbour_request_( void* ); 00127 00128 // adds a new key to the ring 00129 inline void store_new_key_( uint8_t * ); 00130 00131 // returns some "random" time used for waiting 00132 inline millis_t random_work_period_() 00133 { 00134 #ifdef SHAWN 00135 seed_ = ( rand() * ( 1.0 / ( RAND_MAX + 1.0 ) ) ) * 60; 00136 return (millis_t)( seed_ + MIN_WORK_TIME ) * 1000; 00137 #endif 00138 #ifndef SHAWN 00139 seed_++; 00140 seed_ = seed_ % 63; 00141 return (millis_t)( work_period_[seed_] + MIN_WORK_TIME ) * 1000; 00142 #endif 00143 }; 00144 00145 Radio& radio() 00146 { return *radio_; } 00147 00148 Timer& timer() 00149 { return *timer_; } 00150 00151 Debug& debug() 00152 { return *debug_; } 00153 00154 typename Radio::self_pointer_t radio_; 00155 typename Timer::self_pointer_t timer_; 00156 typename Debug::self_pointer_t debug_; 00157 00158 RoutingType *routing_; 00159 00160 // storage container for all the neighbouring nodes (including the offset corresponding to their key) 00161 MapType neighbour_map_; 00162 00163 int callback_id_; 00164 uint16_t seq_nr_; 00165 uint16_t seed_; 00166 uint8_t work_period_[64]; 00167 00168 EschenauerGligorCryptoHandler<OsModel, AES<OsModel> > crypto_handler_; 00169 00170 enum MessageIds 00171 { 00172 EXCHANGE_IDENTIFIERS = 120, 00173 ENCRYPTED_MESSAGE = 121, 00174 NEIGHBOUR_LIST_1 = 122, 00175 NEIGHBOUR_LIST_2 = 123, 00176 KEY_PROPOSAL = 124, 00177 NEIGHBOUR_REQUEST = 125 00178 }; 00179 00180 node_id_t request_from_; 00181 node_id_t request_dest_; 00182 }; 00183 // ----------------------------------------------------------------------- 00184 // ----------------------------------------------------------------------- 00185 // ----------------------------------------------------------------------- 00186 template<typename OsModel_P, 00187 typename Routing_P, 00188 typename NodeidIntMap_P, 00189 typename Radio_P, 00190 typename Debug_P> 00191 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00192 EschenauerGligorAlgorithm() 00193 : radio_ ( 0 ), 00194 timer_ ( 0 ), 00195 debug_ ( 0 ), 00196 callback_id_ ( 0 ), 00197 seq_nr_ ( 0 ) 00198 {} 00199 // ----------------------------------------------------------------------- 00200 template<typename OsModel_P, 00201 typename Routing_P, 00202 typename NodeidIntMap_P, 00203 typename Radio_P, 00204 typename Debug_P> 00205 void 00206 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00207 enable() 00208 { 00209 #ifdef DEBUG_EG 00210 debug().debug( "EschenauerGligorAlgorithm: Booting (Node %i)\n", radio().id() ); 00211 #endif 00212 #ifdef DEBUG_EG 00213 print_ring_(); 00214 #endif 00215 00216 #ifdef SHAWN 00217 srand ( time( NULL ) * ( 3 * radio().id() + 2 ) ); 00218 #endif 00219 00220 seed_ = radio().id(); 00221 00222 work_period_[0] = 29; 00223 work_period_[1] = 25; 00224 work_period_[2] = 43; 00225 work_period_[3] = 36; 00226 work_period_[4] = 52; 00227 work_period_[5] = 10; 00228 work_period_[6] = 53; 00229 work_period_[7] = 5; 00230 work_period_[8] = 23; 00231 work_period_[9] = 58; 00232 work_period_[10] = 56; 00233 work_period_[11] = 29; 00234 work_period_[12] = 53; 00235 work_period_[13] = 21; 00236 work_period_[14] = 41; 00237 work_period_[15] = 0; 00238 work_period_[16] = 20; 00239 work_period_[17] = 13; 00240 work_period_[18] = 54; 00241 work_period_[19] = 29; 00242 work_period_[20] = 43; 00243 work_period_[21] = 20; 00244 work_period_[22] = 4; 00245 work_period_[23] = 22; 00246 work_period_[24] = 2; 00247 work_period_[25] = 42; 00248 work_period_[26] = 0; 00249 work_period_[27] = 28; 00250 work_period_[28] = 52; 00251 work_period_[29] = 28; 00252 work_period_[30] = 40; 00253 work_period_[31] = 21; 00254 work_period_[32] = 54; 00255 work_period_[33] = 23; 00256 work_period_[34] = 58; 00257 work_period_[35] = 46; 00258 work_period_[36] = 33; 00259 work_period_[37] = 51; 00260 work_period_[38] = 52; 00261 work_period_[39] = 57; 00262 work_period_[40] = 50; 00263 work_period_[41] = 49; 00264 work_period_[42] = 27; 00265 work_period_[43] = 44; 00266 work_period_[44] = 10; 00267 work_period_[45] = 8; 00268 work_period_[46] = 44; 00269 work_period_[47] = 31; 00270 work_period_[48] = 22; 00271 work_period_[49] = 39; 00272 work_period_[50] = 0; 00273 work_period_[51] = 5; 00274 work_period_[52] = 59; 00275 work_period_[53] = 5; 00276 work_period_[54] = 27; 00277 work_period_[55] = 2; 00278 work_period_[56] = 47; 00279 work_period_[57] = 28; 00280 work_period_[58] = 31; 00281 work_period_[59] = 40; 00282 work_period_[60] = 56; 00283 work_period_[61] = 11; 00284 work_period_[62] = 2; 00285 work_period_[63] = 50; 00286 00287 millis_t time = random_work_period_(); 00288 00289 radio().enable_radio(); 00290 radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00291 routing_->template reg_recv_callback<self_type, &self_type::receive>( this ); 00292 timer().template set_timer<self_type, &self_type::timer_elapsed_>( time, this, 0 ); 00293 } 00294 // ----------------------------------------------------------------------- 00295 template<typename OsModel_P, 00296 typename Routing_P, 00297 typename NodeidIntMap_P, 00298 typename Radio_P, 00299 typename Debug_P> 00300 void 00301 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00302 disable() 00303 { 00304 #ifdef DEBUG_EG 00305 debug().debug( "EschenauerGligorAlgorithm: Disable\n" ); 00306 #endif 00307 00308 routing_->unreg_recv_callback(); 00309 } 00310 // ----------------------------------------------------------------------- 00311 template<typename OsModel_P, 00312 typename Routing_P, 00313 typename NodeidIntMap_P, 00314 typename Radio_P, 00315 typename Debug_P> 00316 void 00317 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00318 receive( node_id_t from, size_t len, block_data_t *data ) 00319 { 00320 if( from == radio().id() ) 00321 return; 00322 00323 message_id_t msg_id = *data; 00324 Message *message = (Message *)data; 00325 00326 switch( msg_id ) 00327 { 00328 // we got a list of key identifiers 00329 case EXCHANGE_IDENTIFIERS: 00330 process_exchange_identifiers_( from, message ); 00331 break; 00332 // some encrypted content was sent over the network 00333 case ENCRYPTED_MESSAGE: 00334 process_encrypted_message_( from, message ); 00335 break; 00336 // some neighbour of us wants to establish a path using a secondary node 00337 case NEIGHBOUR_LIST_1: 00338 process_neighbour_list_( from, message, 1 ); 00339 break; 00340 // some neighbour of us wants to establish a path using a secondary and tertiary node 00341 case NEIGHBOUR_LIST_2: 00342 process_neighbour_list_( from, message, 2 ); 00343 break; 00344 // we received a proposal for a identifier-key pair 00345 case KEY_PROPOSAL: 00346 process_key_proposal_( from, message ); 00347 break; 00348 // we need a second level Neighbourhood-Analysis 00349 case NEIGHBOUR_REQUEST: 00350 process_neighbour_request_( from, message ); 00351 break; 00352 } 00353 } 00354 // ----------------------------------------------------------------------- 00355 template<typename OsModel_P, 00356 typename Routing_P, 00357 typename NodeidIntMap_P, 00358 typename Radio_P, 00359 typename Debug_P> 00360 void 00361 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00362 send( node_id_t destination, size_t len, block_data_t *data ) 00363 { 00364 #ifdef DEBUG_EG 00365 debug().debug( "EschenauerGligorAlgorithm: Sending encrypted Message to Node %i (Node %i)\n", destination, radio().id() ); 00366 #endif 00367 00368 Message message; 00369 message.set_msg_id( ENCRYPTED_MESSAGE ); 00370 message.set_node_id( radio().id() ); 00371 message.set_dest_id( destination ); 00372 00373 message.set_seq_nr( 1 ); 00374 00375 // find the next hop to send the message to 00376 RoutingTable *table = routing_->routing_table(); 00377 RoutingTableIterator it = table->find( destination ); 00378 00379 if( it != table->end() && it->second.next_hop != radio().NULL_NODE_ID ) 00380 { 00381 // AES has fixed size 16 Bytes Blocks 00382 uint16_t length_aes = ( len / 16 + 1 ) * 16; 00383 00384 MapTypeIterator itt = neighbour_map_.find( it->second.next_hop ); 00385 00386 if( itt != neighbour_map_.end() ) 00387 { 00388 uint16_t offset = itt->second; 00389 uint8_t key[16]; 00390 00391 if( offset < RING_SIZE ) 00392 memcpy( key, keys + offset * 16, 16 ); 00393 else 00394 memcpy( key, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 00395 00396 uint8_t encrypted[ length_aes ]; 00397 00398 // encrypt it 00399 crypto_handler_.key_setup( key ); 00400 crypto_handler_.encrypt( data, encrypted, length_aes ); 00401 00402 message.set_payload( length_aes, encrypted ); 00403 routing_->send( it->second.next_hop, message.buffer_size(), (uint8_t*)&message ); 00404 } 00405 } 00406 } 00407 // ----------------------------------------------------------------------- 00408 // sends a list containing the own key identifiers 00409 template<typename OsModel_P, 00410 typename Routing_P, 00411 typename NodeidIntMap_P, 00412 typename Radio_P, 00413 typename Debug_P> 00414 void 00415 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00416 send_identifier_list_() 00417 { 00418 #ifdef DEBUG_EG 00419 debug().debug( "EschenauerGligorAlgorithm: Sending Identifier-List (Node %i)\n", radio().id() ); 00420 #endif 00421 00422 Message message; 00423 message.set_msg_id( EXCHANGE_IDENTIFIERS ); 00424 message.set_node_id( radio().id() ); 00425 00426 uint16_t i; 00427 uint8_t k = 0; 00428 uint8_t temp[ RING_SIZE * 2 + NEIGHBOUR_COUNT * 2 ]; 00429 00430 for( i = 0; i < RING_SIZE + NEIGHBOUR_COUNT; i++ ) 00431 { 00432 uint8_t ident[2]; 00433 memcpy( ident, identifiers + i * 2, 2 ); 00434 00435 // do not send blacklisted or unused keys! 00436 if( *( ident ) != 0xff || *( ident + 1 ) != 0xff ) 00437 { 00438 memcpy( temp + k * 2, ident, 2 ); 00439 k++; 00440 } 00441 } 00442 00443 message.set_seq_nr( 1 ); 00444 message.set_payload( (size_t)( k * 2 ), (block_data_t*)temp ); 00445 00446 radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message ); 00447 } 00448 // ----------------------------------------------------------------------- 00449 template<typename OsModel_P, 00450 typename Routing_P, 00451 typename NodeidIntMap_P, 00452 typename Radio_P, 00453 typename Debug_P> 00454 void 00455 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00456 print_ring_() 00457 { 00458 // print ring and identifiers 00459 uint16_t i; 00460 00461 debug().debug( "EschenauerGligorAlgorithm: Keyring (Node %i)\n\n", radio().id() ); 00462 00463 for(i=0; i< RING_SIZE + NEIGHBOUR_COUNT; i++) 00464 { 00465 uint16_t j; 00466 uint8_t ident[2]; 00467 uint8_t key[16]; 00468 00469 memcpy( ident, identifiers + i * 2, 2 ); 00470 00471 // do not display blacklisted or unused keys! 00472 if( *( ident ) != 0xff || *( ident + 1 ) != 0xff ) 00473 { 00474 if( i < RING_SIZE ) 00475 memcpy( key, keys + i * 16, 16 ); 00476 else 00477 memcpy( key, backup_keys + ( i - RING_SIZE ) * 16, 16 ); 00478 00479 debug().debug( "Nr %d: 0x", i ); 00480 debug().debug( "%02x%02x", *( ident + 1 ), *( ident ) ); 00481 debug().debug( " => " ); 00482 for(j=0; j<16; j++){ 00483 debug().debug( "%02x", *( key + j ) ); 00484 } 00485 debug().debug( "\n" ); 00486 } 00487 } 00488 debug().debug( "\n" ); 00489 } 00490 // ----------------------------------------------------------------------- 00491 template<typename OsModel_P, 00492 typename Routing_P, 00493 typename NodeidIntMap_P, 00494 typename Radio_P, 00495 typename Debug_P> 00496 void 00497 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00498 print_neighbours_() 00499 { 00500 // print node_id, ring and identifiers 00501 debug().debug( "EschenauerGligorAlgorithm: Neighbours (Node %i)\n\n", radio().id() ); 00502 00503 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 00504 { 00505 uint16_t i; 00506 uint8_t ident[2]; 00507 uint8_t key[16]; 00508 00509 memcpy( ident, identifiers + it->second * 2, 2 ); 00510 00511 if( it->second < RING_SIZE ) 00512 memcpy( key, keys + it->second * 16, 16 ); 00513 else 00514 memcpy( key, backup_keys + ( it->second - RING_SIZE ) * 16, 16 ); 00515 00516 debug().debug( "Node %i: 0x", it->first ); 00517 debug().debug( "%02x%02x", *( ident + 1 ), *( ident ) ); 00518 debug().debug( " => " ); 00519 for(i=0; i<16; i++){ 00520 debug().debug( "%02x", *( key + i ) ); 00521 } 00522 debug().debug( "\n" ); 00523 } 00524 00525 debug().debug( "\n" ); 00526 } 00527 // ----------------------------------------------------------------------- 00528 template<typename OsModel_P, 00529 typename Routing_P, 00530 typename NodeidIntMap_P, 00531 typename Radio_P, 00532 typename Debug_P> 00533 void 00534 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00535 timer_elapsed_( void* userdata ) 00536 { 00537 #ifdef DEBUG_EG 00538 debug().debug( "EschenauerGligorAlgorithm: Execute TimerElapsed (Node %i)\n", radio().id() ); 00539 #endif 00540 millis_t time = random_work_period_(); 00541 #ifdef DEBUG_EG 00542 debug().debug( "EschenauerGligorAlgorithm: Using %ims as new Timersetting ", time ); 00543 debug().debug( "(Node %i)\n", radio().id() ); 00544 #endif 00545 00546 send_identifier_list_(); 00547 timer().template set_timer<self_type, &self_type::timer_elapsed_>( time, this, 0 ); 00548 } 00549 // ----------------------------------------------------------------------- 00550 template<typename OsModel_P, 00551 typename Routing_P, 00552 typename NodeidIntMap_P, 00553 typename Radio_P, 00554 typename Debug_P> 00555 void 00556 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00557 process_exchange_identifiers_( node_id_t from, Message *message ) 00558 { 00559 uint16_t i; 00560 uint16_t j; 00561 uint8_t found = 0; 00562 uint8_t own[2]; 00563 for( i=0; i < ( message->payload_size() / 2 ); i++ ) 00564 { 00565 uint8_t *foreign = (uint8_t*)( message->payload() + i * 2 ); 00566 00567 // now check whether this identifier is in our list 00568 for( j=0; j < RING_SIZE + NEIGHBOUR_COUNT; j++ ) 00569 { 00570 memcpy( own, identifiers + j * 2, 2 ); 00571 00572 if( *own == *foreign && *( own + 1 ) == *( foreign + 1 ) ) 00573 { 00574 // do not use blacklisted keys (identifier set to 0xffff) 00575 if( *own != 0xff || *( own + 1 ) != 0xff ) 00576 { 00577 found = 1; 00578 break; 00579 } 00580 } 00581 } 00582 if( found ) 00583 break; 00584 } 00585 00586 if( found ) 00587 { 00588 #ifdef DEBUG_EG 00589 debug().debug( "EschenauerGligorAlgorithm: Found common identifier to %u: 0x", message->node_id() ); 00590 debug().debug( "%02x%02x (Node %i)\n", *( own + 1 ), *( own ), radio().id() ); 00591 #endif 00592 // update the used key 00593 neighbour_map_[message->node_id()] = j; 00594 00595 #ifdef DEBUG_EG 00596 print_neighbours_(); 00597 #endif 00598 00599 #ifdef SHAWN 00600 debug().current_time(); 00601 #endif 00602 00603 } 00604 else 00605 { 00606 #ifdef DEBUG_EG 00607 debug().debug( "EschenauerGligorAlgorithm: No common identifier found to %u (Node %i)\n", message->node_id(), radio().id() ); 00608 #endif 00609 00610 send_neighbour_list_( message->node_id() ); 00611 } 00612 } 00613 // ----------------------------------------------------------------------- 00614 template<typename OsModel_P, 00615 typename Routing_P, 00616 typename NodeidIntMap_P, 00617 typename Radio_P, 00618 typename Debug_P> 00619 void 00620 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00621 process_encrypted_message_( node_id_t from, Message *message ) 00622 { 00623 MapTypeIterator it = neighbour_map_.find( from ); 00624 00625 if( it != neighbour_map_.end() ) 00626 { 00627 uint16_t offset = it->second; 00628 uint8_t key[16]; 00629 00630 if( offset < RING_SIZE ) 00631 memcpy( key, keys + offset * 16, 16 ); 00632 else 00633 memcpy( key, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 00634 00635 uint16_t payload_size = message->payload_size(); 00636 uint8_t deciphered[ payload_size ]; 00637 00638 // decrypt it 00639 crypto_handler_.key_setup( (uint8_t*)key ); 00640 crypto_handler_.decrypt( message->payload(), deciphered, payload_size ); 00641 00642 // the message has not reached its destination yet 00643 if( message->dest_id() != radio().id() ) 00644 { 00645 #ifdef DEBUG_EG 00646 debug().debug( "EschenauerGligorAlgorithm: Received Message for Node %i - Forwarding Now... (Node %i)\n", message->dest_id(), radio().id() ); 00647 #endif 00648 00649 RoutingTable *table = routing_->routing_table(); 00650 RoutingTableIterator it = table->find( message->dest_id() ); 00651 if( it != table->end() && it->second.next_hop != radio().NULL_NODE_ID ) 00652 { 00653 MapTypeIterator itt = neighbour_map_.find( it->second.next_hop ); 00654 if( itt != neighbour_map_.end() ) 00655 { 00656 offset = itt->second; 00657 00658 if( offset < RING_SIZE ) 00659 memcpy( key, keys + offset * 16, 16 ); 00660 else 00661 memcpy( key, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 00662 00663 // encrypt it 00664 crypto_handler_.key_setup( (uint8_t*)key ); 00665 crypto_handler_.encrypt( deciphered, deciphered, payload_size ); 00666 message->set_payload( payload_size, deciphered ); 00667 00668 routing_->send( it->second.next_hop, message->buffer_size(), (uint8_t*)message ); 00669 } 00670 } 00671 } 00672 // the message has reached its destination 00673 else 00674 { 00675 #ifdef DEBUG_EG 00676 debug().debug( "EschenauerGligorAlgorithm: Received Message from Node %i (Node %i)\n", message->node_id(), radio().id() ); 00677 #endif 00678 00679 notify_receivers( message->node_id(), payload_size, deciphered ); 00680 } 00681 } 00682 } 00683 // ----------------------------------------------------------------------- 00684 template<typename OsModel_P, 00685 typename Routing_P, 00686 typename NodeidIntMap_P, 00687 typename Radio_P, 00688 typename Debug_P> 00689 void 00690 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00691 send_neighbour_list_( node_id_t destination ) 00692 { 00693 uint8_t i = 0; 00694 00695 Message message; 00696 message.set_node_id( radio().id() ); 00697 00698 message.set_msg_id( NEIGHBOUR_LIST_1 ); 00699 node_id_t temp[ neighbour_map_.size() ]; 00700 00701 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 00702 { 00703 temp[i] = it->first; 00704 i++; 00705 } 00706 00707 message.set_seq_nr( 1 ); 00708 message.set_payload( (size_t)( i * sizeof( node_id_t ) ), ( block_data_t *)temp ); 00709 00710 if( i > 0 ) 00711 { 00712 #ifdef DEBUG_EG 00713 debug().debug( "EschenauerGligorAlgorithm: Sending Neighbour-List (Node %i)\n", radio().id() ); 00714 #endif 00715 00716 routing_->send( destination, message.buffer_size(), ( uint8_t* )&message ); 00717 } 00718 } 00719 // ----------------------------------------------------------------------- 00720 template<typename OsModel_P, 00721 typename Routing_P, 00722 typename NodeidIntMap_P, 00723 typename Radio_P, 00724 typename Debug_P> 00725 void 00726 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00727 process_neighbour_list_( node_id_t from, Message *message, uint8_t mode ) 00728 { 00729 if( mode == 1 ) 00730 { 00731 uint8_t size = message->payload_size() / sizeof( node_id_t ); 00732 uint8_t i; 00733 uint8_t k = 0; 00734 uint16_t candidate = 0xffff; 00735 uint16_t last = 0; 00736 uint8_t flag = 0; 00737 00738 while( k < size ) 00739 { 00740 // this loop basically "sorts" the neighbour list 00741 for( i = 0; i < size; i++ ) 00742 { 00743 uint8_t *bla = (uint8_t *)( message->payload() + i * sizeof( node_id_t ) ); 00744 node_id_t temp; 00745 memcpy( &temp, bla, sizeof( node_id_t ) ); 00746 00747 if( temp < candidate && temp >= last ) 00748 candidate = temp; 00749 } 00750 last = candidate + 1; 00751 flag = 0; 00752 00753 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 00754 { 00755 if( candidate == it->first ) 00756 { 00757 flag = 1; 00758 break; 00759 } 00760 } 00761 if( flag ) break; 00762 k++; 00763 } 00764 00765 // if candidate is != 0xffff it refers to the first common neighbour 00766 if( candidate != 0xffff && flag ) 00767 { 00768 #ifdef DEBUG_EG 00769 debug().debug( "EschenauerGligorAlgorithm: Found common Neighbour to Node %i: %i (Node %i)\n", message->node_id(), candidate, radio().id() ); 00770 #endif 00771 00772 key_proposal_( candidate, candidate, from ); 00773 } 00774 // no common neighbour could be found -> ask neighbours for help! 00775 else 00776 { 00777 send_neighbour_request_( from ); 00778 } 00779 } 00780 // mode is set to 2 00781 else 00782 { 00783 node_id_t *container = ( node_id_t* )message->payload(); 00784 node_id_t destination = *container; 00785 00786 node_id_t via = message->node_id(); 00787 00788 uint8_t size = message->payload_size() / sizeof( node_id_t ); 00789 uint8_t i; 00790 uint8_t k = 0; 00791 uint16_t candidate = 0xffff; 00792 uint16_t last = 0; 00793 uint8_t flag = 0; 00794 00795 container++; 00796 size--; 00797 00798 while( k < size ) 00799 { 00800 // this loop basically "sorts" the neighbour list 00801 for( i = 0; i < size; i++ ) 00802 { 00803 uint8_t *bla = (uint8_t *)( message->payload() + i * sizeof( node_id_t ) ); 00804 node_id_t temp; 00805 memcpy( &temp, bla, sizeof( node_id_t ) ); 00806 00807 if( temp < candidate && temp >= last ) 00808 candidate = temp; 00809 } 00810 last = candidate + 1; 00811 flag = 0; 00812 00813 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 00814 { 00815 if( candidate == it->first ) 00816 { 00817 flag = 1; 00818 break; 00819 } 00820 } 00821 if( flag ) break; 00822 k++; 00823 } 00824 00825 // if candidate is != 0xffff it refers to the first common neighbour 00826 if( candidate != 0xffff && flag ) 00827 { 00828 #ifdef DEBUG_EG 00829 debug().debug( "EschenauerGligorAlgorithm: Found common Neighbour to Node %i via %i: %i (Node %i)\n", destination, via, candidate, radio().id() ); 00830 #endif 00831 00832 key_proposal_( candidate, via, destination ); 00833 } 00834 } 00835 } 00836 // ----------------------------------------------------------------------- 00837 template<typename OsModel_P, 00838 typename Routing_P, 00839 typename NodeidIntMap_P, 00840 typename Radio_P, 00841 typename Debug_P> 00842 void 00843 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00844 key_proposal_( node_id_t via, node_id_t via2, node_id_t destination ) 00845 { 00846 // get first nonassigned key! 00847 uint16_t i; 00848 uint8_t flag = 0; 00849 for( i = 0; i < RING_SIZE + NEIGHBOUR_COUNT; i++ ) 00850 { 00851 uint8_t ident[2]; 00852 memcpy( ident, identifiers + i * 2, 2 ); 00853 00854 // do not test blacklisted or unused keys! 00855 if( *( ident ) != 0xff || *( ident + 1 ) != 0xff ) 00856 { 00857 flag = 1; 00858 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 00859 { 00860 if( it->second == i ) 00861 flag = 0; 00862 } 00863 00864 if( flag ) 00865 break; 00866 } 00867 } 00868 00869 if( flag ) 00870 { 00871 send_key_proposal_( via, via2, destination, i ); 00872 } 00873 } 00874 // ----------------------------------------------------------------------- 00875 template<typename OsModel_P, 00876 typename Routing_P, 00877 typename NodeidIntMap_P, 00878 typename Radio_P, 00879 typename Debug_P> 00880 void 00881 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00882 send_key_proposal_( node_id_t via, node_id_t via2, node_id_t destination, uint16_t offset ) 00883 { 00884 #ifdef DEBUG_EG 00885 debug().debug( "EschenauerGligorAlgorithm: Found unused Key at Offset %i (Node %i)\n", offset, radio().id() ); 00886 #endif 00887 00888 #ifdef DEBUG_EG 00889 debug().debug( "EschenauerGligorAlgorithm: Sending Key Proposal to Node %i via %i (Node %i)\n", destination, via, radio().id() ); 00890 #endif 00891 00892 Message message; 00893 message.set_msg_id( KEY_PROPOSAL ); 00894 message.set_node_id( radio().id() ); 00895 message.set_dest_id( destination ); 00896 00897 message.set_seq_nr( 1 ); 00898 00899 // get identifier and key 00900 uint8_t data[ 18 ]; 00901 memcpy( data, identifiers + offset * 2, 2 ); 00902 00903 if( offset < RING_SIZE ) 00904 memcpy( data + 2, keys + offset * 16, 16 ); 00905 else 00906 memcpy( data + 2, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 00907 00908 RoutingTable *table = routing_->routing_table(); 00909 RoutingTableIterator it = table->find( via ); 00910 00911 if( it != table->end() ) 00912 { 00913 // AES has fixed size 16 Bytes Blocks 00914 uint16_t length_aes = ( 18 / 16 + 1 ) * 16; 00915 00916 MapTypeIterator itt = neighbour_map_.find( via ); 00917 00918 print_neighbours_(); 00919 00920 if( itt != neighbour_map_.end() ) 00921 { 00922 uint16_t offset = itt->second; 00923 uint8_t key[16]; 00924 00925 if( offset < RING_SIZE ) 00926 memcpy( key, keys + offset * 16, 16 ); 00927 else 00928 memcpy( key, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 00929 00930 uint8_t encrypted[ length_aes + sizeof( node_id_t ) ]; 00931 00932 // encrypt it 00933 crypto_handler_.key_setup( key ); 00934 crypto_handler_.encrypt( data, encrypted, length_aes ); 00935 00936 // store via2 in the payload 00937 memcpy( encrypted + length_aes, ( uint8_t* )&via2, sizeof( node_id_t ) ); 00938 00939 message.set_payload( length_aes + sizeof( node_id_t ), encrypted ); 00940 routing_->send( via, message.buffer_size(), (uint8_t*)&message ); 00941 } 00942 } 00943 } 00944 // ----------------------------------------------------------------------- 00945 template<typename OsModel_P, 00946 typename Routing_P, 00947 typename NodeidIntMap_P, 00948 typename Radio_P, 00949 typename Debug_P> 00950 void 00951 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 00952 process_key_proposal_( node_id_t from, Message *message ) 00953 { 00954 MapTypeIterator it = neighbour_map_.find( from ); 00955 00956 if( it != neighbour_map_.end() ) 00957 { 00958 uint16_t offset = it->second; 00959 uint8_t key[16]; 00960 00961 if( offset < RING_SIZE ) 00962 memcpy( key, keys + offset * 16, 16 ); 00963 else 00964 memcpy( key, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 00965 00966 uint16_t payload_size = message->payload_size() - sizeof( node_id_t ); 00967 uint8_t deciphered[ payload_size + sizeof( node_id_t ) ]; 00968 00969 // decrypt it 00970 crypto_handler_.key_setup( (uint8_t*)key ); 00971 crypto_handler_.decrypt( message->payload(), deciphered, payload_size ); 00972 00973 node_id_t *via = ( node_id_t* )( message->payload() + payload_size ); 00974 00975 // the message has not reached its destination yet 00976 if( message->dest_id() != radio().id() ) 00977 { 00978 #ifdef DEBUG_EG 00979 debug().debug( "EschenauerGligorAlgorithm: Received Key Proposal for Node %i - Forwarding Now... (Node %i)\n", message->dest_id(), radio().id() ); 00980 #endif 00981 00982 node_id_t next; 00983 00984 if( radio().id() == *via ){ 00985 next = message->dest_id(); 00986 if( from != message->node_id() ) 00987 *via = from; 00988 } 00989 else 00990 { 00991 next = *via; 00992 } 00993 00994 RoutingTable *table = routing_->routing_table(); 00995 RoutingTableIterator it = table->find( next ); 00996 if( it != table->end() && it->second.next_hop != radio().NULL_NODE_ID ) 00997 { 00998 MapTypeIterator itt = neighbour_map_.find( it->second.next_hop ); 00999 if( itt != neighbour_map_.end() ) 01000 { 01001 offset = itt->second; 01002 01003 if( offset < RING_SIZE ) 01004 memcpy( key, keys + offset * 16, 16 ); 01005 else 01006 memcpy( key, backup_keys + ( offset - RING_SIZE ) * 16, 16 ); 01007 01008 // encrypt it 01009 crypto_handler_.key_setup( (uint8_t*)key ); 01010 crypto_handler_.encrypt( deciphered, deciphered, payload_size ); 01011 01012 // store via in the payload 01013 memcpy( deciphered + payload_size, ( uint8_t* )via, sizeof( node_id_t ) ); 01014 01015 message->set_payload( payload_size + sizeof( node_id_t ), deciphered ); 01016 01017 routing_->send( it->second.next_hop, message->buffer_size(), (uint8_t*)message ); 01018 } 01019 } 01020 } 01021 // the message has reached its destination 01022 else 01023 { 01024 #ifdef DEBUG_EG 01025 debug().debug( "EschenauerGligorAlgorithm: Received Key Proposal from Node %i (Node %i)\n", message->node_id(), radio().id() ); 01026 #endif 01027 01028 // get first nonassigned key! 01029 uint16_t i; 01030 uint8_t flag = 0; 01031 uint8_t ident[2]; 01032 for(i=0; i< RING_SIZE + NEIGHBOUR_COUNT; i++) 01033 { 01034 memcpy( ident, identifiers + i * 2, 2 ); 01035 01036 // do not test blacklisted or unused keys! 01037 if( *( ident ) != 0xff || *( ident + 1 ) != 0xff ) 01038 { 01039 flag = 1; 01040 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 01041 { 01042 if( it->second == i ) 01043 flag = 0; 01044 } 01045 if( flag ) 01046 break; 01047 } 01048 } 01049 01050 if( flag ) 01051 { 01052 uint16_t own_ident, foreign_ident; 01053 memcpy( &own_ident, ident, 2 ); 01054 memcpy( &foreign_ident, deciphered, 2 ); 01055 01056 if( own_ident < foreign_ident ) 01057 { 01058 send_key_proposal_( from, *via, message->node_id(), i ); 01059 } 01060 else 01061 { 01062 store_new_key_( deciphered ); 01063 } 01064 } 01065 else 01066 { 01067 store_new_key_( deciphered ); 01068 } 01069 } 01070 } 01071 } 01072 // ----------------------------------------------------------------------- 01073 template<typename OsModel_P, 01074 typename Routing_P, 01075 typename NodeidIntMap_P, 01076 typename Radio_P, 01077 typename Debug_P> 01078 void 01079 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 01080 store_new_key_( uint8_t *data ) 01081 { 01082 // check whether this key has already been stored - this case occurs 01083 // because of the random waiting times between distributing the identifier lists 01084 uint16_t i; 01085 uint8_t flag = 1; 01086 uint8_t ident[2]; 01087 01088 for( i = RING_SIZE; i < RING_SIZE + NEIGHBOUR_COUNT; i++ ) 01089 { 01090 memcpy( ident, identifiers + i * 2, 2 ); 01091 01092 if( *( ident ) == *( data ) && *( ident + 1 ) == *( data + 1 ) ) 01093 { 01094 flag = 0; 01095 break; 01096 } 01097 } 01098 01099 if( flag ) 01100 { 01101 // get first unused or blacklisted key! 01102 flag = 0; 01103 01104 for( i = RING_SIZE; i < RING_SIZE + NEIGHBOUR_COUNT; i++ ) 01105 { 01106 memcpy( ident, identifiers + i * 2, 2 ); 01107 01108 if( *( ident ) == 0xff && *( ident + 1 ) == 0xff ) 01109 { 01110 flag = 1; 01111 break; 01112 } 01113 } 01114 01115 if( flag ) 01116 { 01117 #ifdef DEBUG_EG 01118 debug().debug( "EschenauerGligorAlgorithm: Added new Key to the Ring (Node %i)\n", radio().id() ); 01119 #endif 01120 01121 memcpy( identifiers + i * 2, data, 2 ); 01122 memcpy( backup_keys + ( i - RING_SIZE ) * 16, data + 2, 16 ); 01123 01124 send_identifier_list_(); 01125 } 01126 } 01127 } 01128 // ----------------------------------------------------------------------- 01129 template<typename OsModel_P, 01130 typename Routing_P, 01131 typename NodeidIntMap_P, 01132 typename Radio_P, 01133 typename Debug_P> 01134 void 01135 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 01136 send_neighbour_request_( node_id_t destination ) 01137 { 01138 #ifdef DEBUG_EG 01139 debug().debug( "EschenauerGligorAlgorithm: Sending Neighbour-Request (Node %i)\n", radio().id() ); 01140 #endif 01141 01142 Message message; 01143 message.set_msg_id( NEIGHBOUR_REQUEST ); 01144 message.set_node_id( radio().id() ); 01145 message.set_seq_nr( 2 ); 01146 message.set_payload( (size_t)( sizeof( node_id_t ) ), (block_data_t*)&destination ); 01147 01148 radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message ); 01149 } 01150 // ----------------------------------------------------------------------- 01151 template<typename OsModel_P, 01152 typename Routing_P, 01153 typename NodeidIntMap_P, 01154 typename Radio_P, 01155 typename Debug_P> 01156 void 01157 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 01158 process_neighbour_request_( node_id_t from, Message *message ) 01159 { 01160 node_id_t *destination = ( node_id_t* )message->payload(); 01161 request_from_ = from; 01162 request_dest_ = *destination; 01163 01164 millis_t time = ( random_work_period_() - MIN_WORK_TIME * 1000 ) / 30; 01165 timer().template set_timer<self_type, &self_type::work_neighbour_request_>( time, this, 0 ); 01166 } 01167 // ----------------------------------------------------------------------- 01168 template<typename OsModel_P, 01169 typename Routing_P, 01170 typename NodeidIntMap_P, 01171 typename Radio_P, 01172 typename Debug_P> 01173 void 01174 EschenauerGligorAlgorithm<OsModel_P, Routing_P, NodeidIntMap_P, Radio_P, Debug_P>:: 01175 work_neighbour_request_( void *userdata ) 01176 { 01177 // check whether we have an encrypted link to the sending node 01178 MapTypeIterator it = neighbour_map_.find( request_from_ ); 01179 if( it != neighbour_map_.end() ) 01180 { 01181 uint8_t i = 1; 01182 01183 Message message; 01184 message.set_node_id( radio().id() ); 01185 01186 message.set_msg_id( NEIGHBOUR_LIST_2 ); 01187 node_id_t temp[ neighbour_map_.size() + 1 ]; 01188 01189 temp[0] = request_from_; 01190 01191 // build a list of all the neighbours we have an encrypted link to 01192 for( MapTypeIterator it = neighbour_map_.begin(); it != neighbour_map_.end(); ++it ) 01193 { 01194 if( it-> first != request_from_ ) 01195 { 01196 temp[i] = it->first; 01197 i++; 01198 } 01199 } 01200 01201 message.set_seq_nr( 1 ); 01202 message.set_payload( (size_t)( i * sizeof( node_id_t ) ), ( block_data_t* )temp ); 01203 01204 if( i > 1 ) 01205 { 01206 #ifdef DEBUG_EG 01207 debug().debug( "EschenauerGligorAlgorithm: Sending Neighbour-List Depth 2 (Node %i)\n", radio().id() ); 01208 #endif 01209 01210 routing_->send( request_dest_, message.buffer_size(), (uint8_t*)&message ); 01211 } 01212 } 01213 } 01214 } 01215 #endif